Initialization of an ArrayList in one line

Macarse Source

I want 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?

javacollectionsarraylistinitialization

Answers

answered 9 years ago coobird #1

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 9 years ago Tom #2

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"));

answered 8 years ago Jordão #3

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 8 years ago George #4

import com.google.common.collect.ImmutableList;

....

List<String> places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");

answered 8 years ago Christoffer Hammarström #5

The simple answer

In Java 8 or earlier:

List<String> strings = Arrays.asList("foo", "bar", "baz");

This will give you a List backed by the array, so it cannot change length.
But you can call List.set, so it's still mutable.


In Java 9:

List<String> strings = List.of("foo", "bar", "baz");

This will give you an immutable List, so it cannot be changed.
Which is what you want in most cases where you're prepopulating it.


The shorter answer

You can make Arrays.asList even shorter with a static import:

List<String> strings = asList("foo", "bar", "baz");

The static import:

import static java.util.Arrays.asList;  

Which any modern IDE will suggest and automatically do for you.
For example in IntelliJ IDEA you press Alt+Enter and select Static import method....


However, i don't recommend shortening the Java 9 List.of method, because having just of becomes confusing.
List.of is already short enough and reads well.


Using Streams

Why 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 Streams:

Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
                                       Stream.of("baz", "qux"));

Or you can go from a Stream to a List:

List<String> strings = Stream.of("foo", "bar", "baz").collect(toList());

But preferably, just use the Stream without collecting it to a List.


If you really specifically need a java.util.ArrayList

(You probably don't.)
To quote JEP 269 (emphasis mine):

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.


If you want to both prepopulate an ArrayList and add to it afterwards (why?), use

List<String> strings = new ArrayList<>(asList("foo", "bar", "baz"));

or in Java 9:

List<String> strings = new ArrayList<>(List.of("foo", "bar", "baz"));

or using Stream:

List<String> strings = Stream.of("foo", "bar", "baz")
                             .collect(toCollection(ArrayList::new));

But again, it's better to just use the Stream directly instead of collecting it to a List.


Program to interfaces, not to implementations

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:

// Iterable if you just need iteration, for (String s : strings):
Iterable<String> strings = new ArrayList<>();   

// Collection if you also need .size() or .stream():
Collection<String> strings = new ArrayList<>(); 

// List if you also need .get(index):
List<String> strings = new ArrayList<>();       

// Don't declare a specific list implementation
// unless you're sure you need it:
ArrayList<String> strings = new ArrayList<>();  // You don't need 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 7 years ago Randyaa #6

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 6 years ago Dawg #7

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 6 years ago abaelter #8

public static <T> List<T> asList(T... a) {
    return new ArrayList<T>(a);
}

This is the implementation of Arrays.asList, so you could go with

ArrayList<String> arr = (ArrayList<String>) Arrays.asList("1", "2");

answered 5 years ago Adrian #9

Actually, it's possible to do it in one line:

Arrays.asList(new MyClass[] {new MyClass("arg1"), new MyClass("arg2")})

answered 5 years ago user439407 #10

(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, esp. if you need an unbounded list or need to use inheritance.

answered 5 years ago Ozzy #11

Like Tom said:

List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");

But since you complained of wanting an ArrayList, you should firstly 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 of '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 time of initialisation). And if that's an option for you:

String[] places = {"Buenos Aires", "Córdoba", "La Plata"};

In case you don't care of 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 future you need a bit more than just the place name, you need a country code too. Assuming this is still a predefined list which 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;
    }
}

Enum's 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 5 years ago Paweł Adamski #12

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 5 years ago user2801794 #13

Simply use below code as follows.

List<String> list = new ArrayList<String>() {{
            add("A");
            add("B");
            add("C");
}};

answered 4 years ago Mark #14

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 4 years ago Ran Adler #15

List<String> names = Arrays.asList("2","@2234","21","11");

answered 4 years ago Manoj Kumar #16

For me Arrays.asList() is the best and convenient one. I always like to initialize that way. If you are a beginner into Java Collections then I would like you to refer ArrayList initialization

answered 4 years ago Richard B #17

About the most compact way to do this is:

Double array[] = { 1.0, 2.0, 3.0};
List<Double> list = Arrays.asList(array);

answered 3 years ago Donald Raab #18

With Eclipse Collections (formerly GS 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 3 years ago ViliusK #19

Collections.singletonList(messageBody)

If you'd need to have a list of one item!

Collections is from java.util package.

answered 2 years ago user1452701 #20

In Apple WebObjects Foundation framework you can do this.

NSArray<String> places1 = new NSArray<String>("Buenos Aires", "Córdoba", "La Plata");
NSMutableArray<String> places2 = new NSMutableArray<String>("Buenos Aires", "Córdoba", "La Plata");
List<String> places3 = new NSMutableArray<String>("Buenos Aires", "Córdoba", "La Plata");

The WebObjects Foundation framework was ported from Objective-C to Java more than a decade ago and was updated after Java 5 added support for generics... I wonder why something similar was not implemented in Java Collections classes.

answered 2 years ago Ant20 #21

Try with this code line:

Collections.singletonList(provider)

answered 2 years ago Cherif #22

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 2 years ago Akash Manngroliya #23

Yes with the help of Arrays you can initialize array list in one line,

List<String> strlist= Arrays.asList("aaa", "bbb", "ccc");

answered 2 years ago user_3380739 #24

Here is code by AbacusUtil

// ArrayList
List<String> list = N.asList("Buenos Aires", "Córdoba", "La Plata");
// HashSet
Set<String> set = N.asSet("Buenos Aires", "Córdoba", "La Plata");
// HashMap
Map<String, Integer> map = N.asMap("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);

// Or for Immutable List/Set/Map
ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet.of("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet.of("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);

// The most efficient way, which is similar with Arrays.asList(...) in JDK. 
// but returns a flexible-size list backed by the specified array.
List<String> set = Array.asList("Buenos Aires", "Córdoba", "La Plata");

Declaration: I'm the developer of AbacusUtil.

answered 2 years ago Mahesha999 #25

Sometimes I just feel that people should simply use Groovy and let Java rest in peace. The good thing is that it runs on the JVM, so you can copy paste pure Java code anywhere in a Groovy file, and it will just work.

About declaring list in one line, this is how it looks in Groovy:

def list1 = [1,2,3]

That's it, maan!!!

Here is more on Groovy lists.

Extras

Declaring a map in Groovy in one line:

def map1 = [key1:1,key2:2]

Here is more on Groovy maps.

Reading a JSON file,

{ "map1":{"map2":{"key":"value1"}}}

in one line as follows:

String value = new JsonSlurper().parse("path\\to\\file")["map1"]["map2"]["key"]

or

String value = new JsonSlurper().parse("path\\to\\file").map1.map2.key

Both sets value to value1.

Imagine doing the same with Jackson API. You have to write corresponding POJOs for map1 and map2. Then compile. Also every time the JSON changes, you have to reflect those changes in POJOs. This fully defeats goal of making functionality JSON configurable. It's the deadly configure-code-recompile chain. Not just configure and go.

(Sometimes,) I cry when I was asked to use Java. Why world why???? (or please enlighten me if am wrong...will reduce a lot of my pain in Java World)

answered 2 years ago Carlos Heuberger #26

Java 9 has the following method to create an immutable list:

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 1 year ago nullpointer #27

With Java 9, as suggested in JDK Enhancement Proposal - 269, this could be achieved using collection literals now as -

List<String> list = List.of("A", "B", "C");

Set<String> set = Set.of("A", "B", "C");

Also 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 as well. Further clarified in the JEP doc 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.

Chained read about the same ~> What is the point of overloaded Convenience Factory Methods

answered 1 year ago Henok T #28

Here is another way:

List<String> values = Stream.of("One", "Two").collect(Collectors.toList());

answered 1 year ago rashedcs #29

You can use the below statements:

Code Snippet:

String [] arr = {"Sharlock", "Homes", "Watson"};

List<String> names = Arrays.asList(arr);

answered 12 months ago yegor256 #30

You can use StickyList from Cactoos:

List<String> names = new StickyList<>(
  "Scott Fitzgerald", "Fyodor Dostoyevsky"
);

answered 9 months ago Mohit Tyagi #31

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:

  1. Space Efficiency
  2. Immutability
  3. Thread Safe

See this post for more details -> What is the difference between List.of and Arrays.asList?

answered 7 months ago Stefan Reich #32

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");

comments powered by Disqus