views:

218

answers:

2

The Java API docs say the following about Collections.addAll

The behavior of this convenience method is identical to that of c.addAll(Arrays.asList(elements)), but this method is likely to run significantly faster under most implementations.

So if I understand correctly, a) is slower than b):

a)

Collection<Integer> col = new ArrayList<Integer>();
col.addAll(Arrays.asList(1, 2, 3, 4, 5));

b)

Collection<Integer> col = new ArrayList<Integer>();
// Collections.addAll(col, Arrays.asList(1, 2, 3, 4, 5)); <-- won't compile
Collections.addAll(col, 1, 2, 3, 4, 5);

Can anyone explain to me, why that is?

edited: corrected code example. thx to polygenelubricants

+12  A: 

Let's take a closer look at the two of them:

// a)
col.addAll(Arrays.asList(1, 2, 3, 4, 5));

Here's what happens:

  1. varags + autoboxing creates Integer[]
  2. Arrays.asList creates a List<Integer> backed by the array
  3. addAll iterates over a Collection<Integer> using Iterator<Integer>
// b)
Collections.addAll(col, 1, 2, 3, 4, 5);

Here's what happens:

  1. varargs + autoboxing creates Integer[]
  2. addAll iterates over an array (instead of an Iterable<Integer>)

We can see now that b) may be faster because:

  • Arrays.asList call is skipped, i.e. no intermediary List is created.
  • Since the elements are given in an array (thanks to varargs mechanism), iterating over them may be faster than using Iterator.

That said, unless profiling shows otherwise, the difference isn't likely to be "significant". Do not optimize prematurely. While Java Collection Framework classes may be slower than arrays, they perform more than adequately for most applications.

API links

See also

Related questions


Summary

  • If you're adding elements from an array, you can use Collections.addAll(col, arr)
    • Remember that varargs are also done using arrays
  • If you're adding elements from a Collection, use col.addAll(otherCol)
    • Do NOT e.g. Collections.addAll(col, otherCol.toArray())
      • Such roundabout way is likely to be slower!
  • It's not that one is supremely faster than the other
    • It's about skipping unnecessary steps given the current situation
polygenelubricants
You're right... I corrected the question.
dertoni
@polygenelubricants: new edit: I think now everyone can understand your answer with regard to my errors. :-)
dertoni
My personal opinion is that the documentation is slightly confusing in that regard, as I fail to see how the implementation of that method has anything to do with it. It is the usage of the method, and the fact that you don't have to package up the data in an extra step that makes it faster. Or is there something else about the method that makes it faster as well?
Lasse V. Karlsen
+2  A: 

The only reason it might be faster is that it avoids the call to Arrays.asList which should be relatively cheap since it just wraps the array. Some Collection implementations, for example LinkedList convert the passed collection back to an array before adding the elements, causing additional overhead.

On the other hand, ArrayList.addAll allocates the needed space once before adding any elements and so should be much faster when Collections.addAll requires multiple resizing of the backing array.

In summary, Collections.addAll could be faster when repeatedly adding only a few elements to a collection, but I doubt that this case would ever be a performance bottleneck.

Jörn Horstmann
There's also the iteration factor, i.e. iterating over an array `T[]` (which is what varargs is in Java) vs iterating over a `Collection<E>`, i.e. an `Iterable<E>` through its `Iterator<E>`.
polygenelubricants
for the particular case of an `ArrayList`, you can always `al.ensureCapacity(al.size() + array.length)` first. Though yes, probably not going to be enough of a bottleneck that one would want to make a field an `ArrayList` instead of a `List`.
Carl
@Carl: _Effective Java 2nd Edition, Item 52: Refer to objects by their interfaces_. You should generally not have a field declared as an `ArrayList` instead of a `List`.
polygenelubricants
+1 for pointing out the specific `addAll` implementation quirks of `ArrayList` and `LinkedList`.
polygenelubricants
@polygenelubricants: my comment says that already, if perhaps not as specifically. Legitmate performance concerns can be a reason to violate that particular piece of EJ advice - again, I doubt that's the case here.
Carl