FreakyDan FreakyDan - 6 months ago 19
Java Question

ConcurrentModificationException: .add() vs .addAll()

Why does the following occur? Shouldn't both work?

List<String> items = data;
for( String id : items ) {
List<String> otherItems = otherData;

// 1. addAll()
//Causes ConcurrentModificationException
items.addAll(otherItems);

// 2. .add()
//Doesn't cause exceptions
for( String otherId : otherItems ) {
items.add(otherId);
}
}


Is it because
add()
adds to the collection Items, but
addAll()
creates a new collection thus modifying Items to be a different instance of List?

Edit
items
and
otherItems
are of concrete type
ArrayList<String>
.

Answer

Neither operation is proper, since it modifies the collection while iterating it.

Examining the implementation of ArrayList shows that calling either add or addAll should successfully throw the ConcurrentModificationException on the next loop iteration. The fact that it isn't doing that for add means that either there is an obscure bug in the ArrayList class for the particular version of Java you have; or (more likely) otherItems is empty, so in the second case, you aren't actually calling add at all.

I'm sure otherItems must be empty, because if adding to the Items list "worked" in the way you want, then it would grow every time around the loop, causing it to loop indefinitely until dying with an OutOfMemoryError.