Friday, June 8, 2012

Initialization of an ArrayList in one line


I am willing to create a list of options to test something.



I was doing:




ArrayList<String> places = new ArrayList<String>();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");



I refactor the code doing:




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



Is there a better way of doing this?



Thanks for reading!


Source: Tips4all

9 comments:

  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 be nice is if the Collection Literals proposal for Project Coin is accepted, so we can have list literals in Java 7:

    List<String> list = ["A", "B", "C"];


    Unfortunately it won't help you here, as it will initialize a List rather than an ArrayList, and furthermore, it's not available yet, if it ever will be.

    ReplyDelete
  2. It'd 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");

    ReplyDelete
  3. import com.google.common.collect.ImmutableList;

    ....

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

    ReplyDelete
  4. 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");

    ReplyDelete
  5. 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.

    UPDATE: 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;
    }

    ReplyDelete
  6. Pretty much the simplest way if you must have an ArrayList is just

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


    Otherwise you should in most cases just use

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


    You said you've declared the list as an ArrayList in your code, but you should not do that unless you're using some member of ArrayList that's not in List, for example ArrayList.ensureCapacity().

    Usually you should just declare variables by the most general interface that you are going to use, which for lists is usually List, and initialize them with the specific implementation, for example ArrayList or LinkedList.

    Work with interfaces, not implementations, otherwise you will find that you have to change in more than one place when you want to use another implementation.

    Another example would be always declaring variable an InputStream even though it is usually a FileInputStream, because one day soon you or somebody else will want to use some other kind of InputStream.

    ReplyDelete
  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.

    ReplyDelete
  8. To setup a list filled with N copies of a default object:

    ArrayList<Object> list = new ArrayList<Object>(
    Collections.nCopies(1000, new Object()));

    ReplyDelete
  9. Just observed it is working in a very simple way as follows:

    ArrayList arrList = new ArrayList() {"1",2,3,"4" };

    List<Customer> listCustomer = new List<Customer>() { new Customer(), new Customer(), new Customer() };


    This is working in C# 3.0
    No Double Braces required. Hope this helps.

    ReplyDelete