Wednesday, December 19, 2007

Removing items from a List in Java

Yesterday I discussed with some colleagues how to remove items from a list in Java while iterating this list. A trivial task it seams and yes it is. But still there are several options of how to do this, some of which have interesting side effects.

Here a small summary of what I found out while investigating this topic together with some examples. All examples assume a 5 elements list reading as follows ["item 1 remove", "item 2", "item 3 remove", "item 4", "item 5 remove"]

So lets start with a non working example:
for (String val : list) {
if (val.contains("remove"))
list.remove(val);
}
Well this actually removes the first item, but when moving to the second item a ConcurrentModificationException is thrown. This is because the iterator of the list, at least if the list is an extension of AbstractList, checks in the next() method if there was a modification to the list. If so next() fails.

The next example also uses the for-each loop but breaks after removing the first item.
for (String val : list) {
if (val.contains("remove")) {
list.remove(val);
break;
}
}
This works of course because the next() method of the iterator never gets a chance to check if there was a modification.

From this examples one can clearly see how dangerous it is to call remove(...) in a for-each loop.

So the best way to do this is to use the iterators remove() method. Sadly this method is not available when using the for-each loop so we have to use the good old while(it.hasNext()).

Here is the example for that case:
while (it.hasNext()) {
String val = it.next();
if (val.contains("remove"))
it.remove();
}

Of course calling list.remove(...) would fail like in the for-each loop.

While this was the correct way there is still the question what happens if one uses a normal for loop like in the following example:
for (int i = 0; i < list.size(); i++) {
if (list.get(i).contains("remove"))
list.remove(i);
}

Well this works. But careful. The lists size is reduced with each remove. Storing list.size() in a variable and using this variable breaks the program.

So the only good way to remove items from a list while iterating the list is to use a while-loop, a good old fashioned iterator and the iterators remove method.
Post a Comment