Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - new ArrayList(List) vs empty ArrayList() + add(element)

Tags:

java

arraylist

I've learned today that you can create a new ArrayList object utilizing a static method like so:

List<String> listDummy = Arrays.asList("Coding", "is", "fun"); 
ArrayList<String> stringList = new ArrayList<>(listDummy);

Or even more concisely:

ArrayList<String> stringList = new ArrayList<>(Arrays.asList("Coding", "is", "fun"));

My question is: How expensive is this performance-wise compared to the "traditional" way? (below)

ArrayList<String> stringList = new ArrayList<>();
stringList.add("Coding");
stringList.add("is");
stringList.add("fun");

I realize the upper way of creating an ArrayList includes an extra List object creation, however, I prefer the shorter and more compact syntax to an extent that I'm willing to sacrifice some performance but gotta draw the line somewhere.

PS. leaving the type information(<>) empty in "new ArrayList<>()" is a Java SE 7 feature, not an error.

Thank you beforehand for any answers!

like image 799
straville Avatar asked Jun 11 '13 10:06

straville


5 Answers

The performance difference is likely to be 30 - 300 ns depending on your system and how warmed up your code is. I suspect the performance difference is small.

I always say, if in doubt; write the code as simpler and clear as you can and it will often perform ok as well.

like image 86
Peter Lawrey Avatar answered Oct 17 '22 07:10

Peter Lawrey


The usual add() way calls three methods.

The asList() way makes an array, then does clone() on it (which does a shallow copy), then does copy all the elements manually because of this bug. And afterwards, if you want to add another element to stringList, the array will have to be made larger and elements re-copied, because the size was exact for the elements provided. (all this is implementation dependant and assumes Oracle JDK)

For three elements, the latter will be slower, but for any practical use, it will be negligible. For many elements, the two approaches might get equal in performance and the former one might even get slower.

Write what you think will read the best, the performance penalty is minimal and you should not care about it until it proves itself to be bottleneck.


All that said, if you're after consice syntax, you could like Google Guava's Lists:

List<String> stringList = Lists.newArrayList("Coding", "is", "fun");

I haven't used a classic ArrayList constructor for quite a while now.

like image 21
Petr Janeček Avatar answered Oct 17 '22 06:10

Petr Janeček


You can do it in one line without creating additional lists:

ArrayList<String> stringList = new ArrayList<>(){{
    add("Coding");
    add("is");
    add("fun");
}};

This is an anonymous class, which is a subclass of ArrayList, with an instance block.

like image 40
Bohemian Avatar answered Oct 17 '22 05:10

Bohemian


The list you get from Arrays.asList is already an ArrayList, so it is not necessary to wrap it with an ArrayList again:

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

Caveat: The list is read-only, so if you need to write it, you will need to wrap it indeed using new ArrayList(..).

Nevertheless, I think using Arrays.asList should be better than creating a list using repeated calls of "add", because the ArrayList's internal array is initialized with the correct size. So the best way would be

List<String> myList= Arrays.asList("Coding", "is", "fun");
// or if you need to write the list
List<String> myList = new ArrayList(Arrays.asList("Coding", "is", "fun"));

Also this is the most readable IMHO, and readability for me always wins over very small performance gains unless you really need that extra performance. If you really need to do performance tuning, use a profiler. The bottleneck is usually where you wouldn't expect it to be. A profiler can give you exact information about what parts of your program are slow and you can optimize them as needed.

like image 34
Jan Thomä Avatar answered Oct 17 '22 05:10

Jan Thomä


If you are not going to add /remove elements from the list after creation then the best way is not to create ArrayList at all, this will be really efficient

List<String> listDummy = Arrays.asList("Coding", "is", "fun"); 

otherwise new ArrayList<>(listDummy) is more efficient than manual adding elements one by one, see ArrayList(Collection) src:

public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    size = elementData.length;
    // c.toArray might (incorrectly) not return Object[] (see 6260652)
    if (elementData.getClass() != Object[].class)
        elementData = Arrays.copyOf(elementData, size, Object[].class);
}

it's optimized:

1) it creates the array of exact size
2) it uses native copying of elements

like image 1
Evgeniy Dorofeev Avatar answered Oct 17 '22 05:10

Evgeniy Dorofeev