I wanted to create a list of options for testing purposes. At first, I did this:
ArrayList<String> places = new ArrayList<String>();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");
Then, I refactored the code as follows:
ArrayList<String> places = new ArrayList<String>(
Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
Is there a better way to do this?
ArrasyList<String> places = ["Buenos Aires", "Córdoba", "La Plata"]
- anyone List<Integer> = {1, 2, 3, 4, 5}
in Java. Create and init a mutable array in one line, as I know Python and Swift could do that. - anyone It would be simpler if you were to just declare it as a List
- does it have to be an ArrayList?
List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
Or if you have only one element:
List<String> places = Collections.singletonList("Buenos Aires");
This would mean that places
is immutable (trying to change it will cause an UnsupportedOperationException
exception to be thrown).
To make a mutable list that is a concrete ArrayList
you can create an ArrayList
from the immutable list:
ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
And import the correct package:
import java.util.Arrays;
Answered 2023-09-20 20:18:23
ArrayList
, it would be better design to change the declaration to List
. Specify interfaces, not implementations. - anyone asList(...)
returns a fixed size List
that blows up on mutating operations like remove
and clear
, things the List
contract claims to support. Even if you left declaration as List
, you sill need to use List l = new ArrayList(asList(...))
in order to get an object that doesn't throw OperationNotSupported exceptions. Liskov Substitution Principle anyone? - anyone Actually, probably the "best" way to initialize the ArrayList
is the method you wrote, as it does not need to create a new List
in any way:
ArrayList<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");
The catch is that there is quite a bit of typing required to refer to that list
instance.
There are alternatives, such as making an anonymous inner class with an instance initializer (also known as an "double brace initialization"):
ArrayList<String> list = new ArrayList<String>() {{
add("A");
add("B");
add("C");
}};
However, I'm not too fond of that method because what you end up with is a subclass of ArrayList
which has an instance initializer, and that class is created just to create one object -- that just seems like a little bit overkill to me.
What would have been nice was if the Collection Literals proposal for Project Coin was accepted (it was slated to be introduced in Java 7, but it's not likely to be part of Java 8 either.):
List<String> list = ["A", "B", "C"];
Unfortunately it won't help you here, as it will initialize an immutable List
rather than an ArrayList
, and furthermore, it's not available yet, if it ever will be.
Answered 2023-09-20 20:18:23
List<String> strings = List.of("foo", "bar", "baz");
List.of(...)
will give you an immutable List
, so it cannot be changed.
Which is what you want in most cases where you're prepopulating it.
This does not allow null
elements.
List<String> strings = Arrays.asList("foo", "bar", "baz");
Arrays.asList(...)
will give you a List
* backed by an array, so it cannot change length.
But you can call List.set(...)
, so it's still mutable.
This does allow null
elements.
*
Implementation detail: It's a private nested class inside java.util.Arrays
, named ArrayList
,
which is a different class from java.util.ArrayList
, even though their simple names are the same.
You can make Java 8 Arrays.asList
even shorter with a static import:
import static java.util.Arrays.asList;
...
List<String> strings = asList("foo", "bar", "baz");
Any modern IDE* will suggest and do this for you.
I don't recommend statically importing the List.of
method as just of
, because it's confusing.
*
For example, in IntelliJ IDEA you press Alt+Enter
and select Static import method...
Stream
sWhy does it have to be a List
?
With Java 8 or later you can use a Stream
which is more flexible:
Stream<String> strings = Stream.of("foo", "bar", "baz");
You can concatenate Stream
s:
Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
Stream.of("baz", "qux"));
Or you can go from a Stream
to a List
:
import static java.util.stream.Collectors.toList;
...
var strings = Stream.of("foo", "bar", "baz").toList(); // Java 16
List<String> strings = Stream.of("foo", "bar", "baz").collect(toList()); // Java 8
But preferably, just use the Stream
without collecting it to a List
.
java.util.ArrayList
*If you want to both prepopulate an ArrayList
and add to it afterwards, use
List<String> strings = new ArrayList<>(List.of("foo", "bar"));
or in Java 8 or earlier:
List<String> strings = new ArrayList<>(asList("foo", "bar"));
or using Stream
:
import static java.util.stream.Collectors.toCollection;
List<String> strings = Stream.of("foo", "bar")
.collect(toCollection(ArrayList::new));
Then you can add to it after construction:
strings.add("baz");
But again, it's better to just use the Stream
directly instead of collecting it to a List
.
*You probably don't need specifically an ArrayList
. To quote JEP 269:
There is a small set of use cases for initializing a mutable collection instance with a predefined set of values. It's usually preferable to have those predefined values be in an immutable collection, and then to initialize the mutable collection via a copy constructor.
(emphasis mine)
You said you've declared the list as an ArrayList
in your code, but you should only do that if you're using some member of ArrayList
that's not in List
.
Which you are most likely not doing.
Usually you should just declare variables by the most general interface that you are going to use (e.g. Iterable
, Collection
, or List
), and initialize them with the specific implementation (e.g. ArrayList
, LinkedList
or Arrays.asList()
).
Otherwise you're limiting your code to that specific type, and it'll be harder to change when you want to.
For example, if you're passing an ArrayList
to a void method(...)
:
// Iterable if you just need iteration, for (String s : strings):
void method(Iterable<String> strings) {
for (String s : strings) { ... }
}
// Collection if you also need .size(), .isEmpty(), or .stream():
void method(Collection<String> strings) {
if (!strings.isEmpty()) { strings.stream()... }
}
// List if you also need random access, .get(index):
void method(List<String> strings) {
strings.get(...)
}
// Don't declare a specific list implementation
// unless you're sure you need it:
void method(ArrayList<String> strings) {
??? // You don't want to limit yourself to just ArrayList
}
Another example would be always declaring variable an InputStream
even though it is usually a FileInputStream
or a BufferedInputStream
, because one day soon you or somebody else will want to use some other kind of InputStream
.
Answered 2023-09-20 20:18:23
InputStream
and OutputStream
? java.util.stream.Stream
does not need to be closed. It does need a terminal operation, but you're not going to forget that, because without it the stream does nothing. - anyone java.util.stream.Stream
extends BaseStream
which does have a close()
method because it implements AutoCloseable
. At the very least an IDE is going to complain about a potential resource leak. - anyone AutoCloseable
when it may not need to actually be closed, but that's exactly what they did (see API note). - anyone If you need a simple list of size 1:
List<String> strings = new ArrayList<String>(Collections.singletonList("A"));
If you need a list of several objects:
List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");
Answered 2023-09-20 20:18:23
With Guava you can write:
ArrayList<String> places = Lists.newArrayList("Buenos Aires", "Córdoba", "La Plata");
In Guava there are also other useful static constructors. You can read about them here.
Answered 2023-09-20 20:18:23
java.util.Arrays
such as, List<String> names = Arrays.asList("Beckah", "Sam", "Michael");
- anyone Arrays.asList
creates a list that can't be modified. If the list needs to be modified Lists.newArrayList
will work and Arrays.asList
won't. - anyone With java-9 and above, as suggested in JEP 269: Convenience Factory Methods for Collections, this could be achieved using collection literals now with -
List<String> list = List.of("A", "B", "C");
Set<String> set = Set.of("A", "B", "C");
A similar approach would apply to Map
as well -
Map<String, String> map = Map.of("k1", "v1", "k2", "v2", "k3", "v3")
which is similar to Collection Literals proposal as stated by @coobird. Further clarified in the JEP as well -
Alternatives
Language changes have been considered several times, and rejected:
Project Coin Proposal, 29 March 2009
Project Coin Proposal, 30 March 2009
JEP 186 discussion on lambda-dev, January-March 2014
The language proposals were set aside in preference to a library-based proposal as summarized in this message.
Related: What is the point of overloaded Convenience Factory Methods for Collections in Java 9
Answered 2023-09-20 20:18:23
Collection literals didn't make it into Java 8, but it is possible to use the Stream API to initialize a list in one rather long line:
List<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toList());
If you need to ensure that your List
is an ArrayList
:
ArrayList<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toCollection(ArrayList::new));
Answered 2023-09-20 20:18:23
import com.google.common.collect.ImmutableList;
....
List<String> places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
Answered 2023-09-20 20:18:23
Collections.unmodifiableList(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"))
, which becomes unmodifiableList(asList("Buenos Aires", "Córdoba", "La Plata"))
with static imports. You don't need Google Collections for this. - anyone ImmutableList
to other methods that take a List
, and then you've lost that documentation anyway. - anyone You could create a factory method:
public static ArrayList<String> createArrayList(String ... elements) {
ArrayList<String> list = new ArrayList<String>();
for (String element : elements) {
list.add(element);
}
return list;
}
....
ArrayList<String> places = createArrayList(
"São Paulo", "Rio de Janeiro", "Brasília");
But it's not much better than your first refactoring.
For greater flexibility, it can be generic:
public static <T> ArrayList<T> createArrayList(T ... elements) {
ArrayList<T> list = new ArrayList<T>();
for (T element : elements) {
list.add(element);
}
return list;
}
Answered 2023-09-20 20:18:23
for
with Collections.addAll(elements)
as described here. - anyone In Java 9 we can easily initialize an ArrayList
in a single line:
List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");
or
List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));
This new approach of Java 9 has many advantages over the previous ones:
See this post for more details -> What is the difference between List.of and Arrays.asList?
Answered 2023-09-20 20:18:23
ArrayList
, despite the preceding sentence indicating that it does. - anyone Simply use below code as follows.
List<String> list = new ArrayList<String>() {{
add("A");
add("B");
add("C");
}};
Answered 2023-09-20 20:18:23
About the most compact way to do this is:
Double array[] = { 1.0, 2.0, 3.0};
List<Double> list = Arrays.asList(array);
Answered 2023-09-20 20:18:23
Here is another way:
List<String> values = Stream.of("One", "Two").collect(Collectors.toList());
Answered 2023-09-20 20:18:23
With Eclipse Collections you can write the following:
List<String> list = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");
You can also be more specific about the types and whether they are Mutable or Immutable.
MutableList<String> mList = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableList<String> iList = Lists.immutable.with("Buenos Aires", "Córdoba", "La Plata");
You can also do the same with Sets and Bags:
Set<String> set = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableSet<String> mSet = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet<String> iSet = Sets.immutable.with("Buenos Aires", "Córdoba", "La Plata");
Bag<String> bag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableBag<String> mBag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableBag<String> iBag = Bags.immutable.with("Buenos Aires", "Córdoba", "La Plata");
Note: I am a committer for Eclipse Collections.
Answered 2023-09-20 20:18:23
(Should be a comment, but too long, so new reply). As others have mentioned, the Arrays.asList
method is fixed size, but that's not the only issue with it. It also doesn't handle inheritance very well. For instance, suppose you have the following:
class A {}
class B extends A {}
public List<A> getAList() {
return Arrays.asList(new B());
}
The above results in a compiler error, because List<B>
(which is what is returned by Arrays.asList
) is not a subclass of List<A>
, even though you can add Objects of type B
to a List<A>
object. To get around this, you need to do something like:
new ArrayList<A>(Arrays.<A>asList(b1, b2, b3))
This is probably the best way to go about doing this, especially if you need an unbounded list or need to use inheritance.
Answered 2023-09-20 20:18:23
You can use the below statements:
String [] arr = {"Sharlock", "Homes", "Watson"};
List<String> names = Arrays.asList(arr);
Answered 2023-09-20 20:18:23
letters = Arrays.asList(new String[]{"A", "B", "C"});
- anyone Java 9 has the following method to create an immutable list as documented (or documented as unmodifiable Java 10+):
List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");
which is easily adapted to create a mutable list, if required:
List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));
Similar methods are available for Set
and Map
.
Answered 2023-09-20 20:18:23
Like Tom said:
List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
But since you complained of wanting an ArrayList, you should first know that ArrayList is a subclass of List and you could simply add this line:
ArrayList<String> myPlaces = new ArrayList(places);
Although, that might make you complain about 'performance'.
In that case, it doesn't make sense to me, why, since your list is predefined it wasn't defined as an array (since the size is known at the time of initialization). And if that's an option for you:
String[] places = { "Buenos Aires", "Córdoba", "La Plata" };
In case you don't care about the minor performance differences then you can also copy an array to an ArrayList very simply:
ArrayList<String> myPlaces = new ArrayList(Arrays.asList(places));
Okay, but in the future, you need a bit more than just the place name, you need a country code too. Assuming this is still a predefined list that will never change during run-time, then it's fitting to use an enum
set, which would require re-compilation if the list needed to be changed in the future.
enum Places { BUENOS_AIRES, CORDOBA, LA_PLATA }
would become:
enum Places {
BUENOS_AIRES("Buenos Aires", 123),
CORDOBA("Córdoba", 456),
LA_PLATA("La Plata", 789);
String name;
int code;
Places(String name, int code) {
this.name = name;
this.code = code;
}
}
Enums have a static values
method that returns an array containing all of the values of the enum in the order they are declared, e.g.:
for (Places p : Places.values()) {
System.out.printf("The place %s has code %d%n",
p.name, p.code);
}
In that case, I guess you wouldn't need your ArrayList.
P.S. Randyaa demonstrated another nice way using the static utility method Collections.addAll.
Answered 2023-09-20 20:18:23
Yes with the help of Arrays you can initialize array list in one line,
List<String> strlist= Arrays.asList("aaa", "bbb", "ccc");
Answered 2023-09-20 20:18:23
You can use StickyList
from Cactoos:
List<String> names = new StickyList<>(
"Scott Fitzgerald", "Fyodor Dostoyevsky"
);
Answered 2023-09-20 20:18:23
Using Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
is correct. but Any calls to Arrays.asList()
with zero arguments or only one argument could be replaced with either a call to Collections.singletonList()
or Collections.emptyList()
which will save some memory.
Note: the list returned by Collections.singletonList()
is immutable, while the list returned Arrays.asList()
allows calling the set()
method. This may break the code in rare cases.
Answered 2023-09-20 20:18:23
Try with this code line:
Collections.singletonList(provider)
Answered 2023-09-20 20:18:23
There are multiple ways to create and initialize list in one line.
//Using Double brace initialization
List<String> list1 = new ArrayList<>() {{ add("A"); add("B"); }};
//Immutable List
List<String> list2 = List.of("A", "B");
//Fixed size list. Can't add or remove element, though replacing the element is allowed.
List<String> list3 = Arrays.asList("A", "B");
//Modifiable list
List<String> list4 = new ArrayList<>(Arrays.asList("A", "B"));
//Using Java Stream
List<String> list5 = Stream.of("A", "B").collect(Collectors.toList());
//Thread safe List
List<String> list6 = new CopyOnWriteArrayList<>(Arrays.asList("A", "B"));
Answered 2023-09-20 20:18:23
In Java, you can't do
ArrayList<String> places = new ArrayList<String>( Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
As was pointed out, you'd need to do a double brace initialization:
List<String> places = new ArrayList<String>() {{ add("x"); add("y"); }};
But this may force you into adding an annotation @SuppressWarnings("serial")
or generate a serial UUID which is annoying. Also most code formatters will unwrap that into multiple statements/lines.
Alternatively you can do
List<String> places = Arrays.asList(new String[] {"x", "y" });
but then you may want to do a @SuppressWarnings("unchecked")
.
Also according to javadoc you should be able to do this:
List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
But I'm not able to get it to compile with JDK 1.6.
Answered 2023-09-20 20:18:23
Collections.singletonList(messageBody)
If you'd need to have a list of one item!
Collections is from java.util package.
Answered 2023-09-20 20:18:23
interestingly no one-liner with the other overloaded Stream::collect
method is listed
ArrayList<String> places = Stream.of( "Buenos Aires", "Córdoba", "La Plata" ).collect( ArrayList::new, ArrayList::add, ArrayList::addAll );
Answered 2023-09-20 20:18:23
The best way to do it:
package main_package;
import java.util.ArrayList;
public class Stackkkk {
public static void main(String[] args) {
ArrayList<Object> list = new ArrayList<Object>();
add(list, "1", "2", "3", "4", "5", "6");
System.out.println("I added " + list.size() + " element in one line");
}
public static void add(ArrayList<Object> list, Object... objects) {
for (Object object : objects)
list.add(object);
}
}
Just create a function that can have as many elements as you want and call it to add them in one line.
Answered 2023-09-20 20:18:23
Object
. - anyone Why not make a simple utility function that does this?
static <A> ArrayList<A> ll(A... a) {
ArrayList l = new ArrayList(a.length);
for (A x : a) l.add(x);
return l;
}
"ll
" stands for "literal list".
ArrayList<String> places = ll("Buenos Aires", "Córdoba", "La Plata");
Answered 2023-09-20 20:18:23
list
, the name requires no explanation :) - anyone Simplest way : you can use this approach to add multiple elements to any type of collection like ArrayList and HashSet
ArrayList<String> allViews = new ArrayList<String>();
Collections.addAll(allViews,"hello","world","abc","def","ghi");
Answered 2023-09-20 20:18:23