Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to modify a Collection while iterating using for-each loop without ConcurrentModificationException? [duplicate]

If I modify a Collection while iterating over it using for-each loop, it gives ConcurrentModificationException. Is there any workaround?

like image 201
aps Avatar asked Aug 05 '11 15:08

aps


People also ask

Can you modify collection structure while iterating using for-each loop?

In for-each loop, we can't modify collection, it will throw a ConcurrentModificationException on the other hand with iterator we can modify collection.

Can we modify list while iterating?

Yes, that is a very important point, and all programmers should think about this very carefully. As a general rule in programming, you should avoid mutating an object while iterating over it, unless it is the specific purpose of the function to mutate the original object.

How many ways we can avoid ConcurrentModificationException?

There are two basic approaches: Do not make any changes to a collection while an Iterator loops through it. If you can't stop the underlying collection from being modified during iteration, create a clone of the target data structure and iterate through the clone.


4 Answers

Use Iterator#remove.

This is the only safe way to modify a collection during iteration. For more information, see The Collection Interface tutorial.

If you also need the ability to add elements while iterating, use a ListIterator.

like image 55
mre Avatar answered Sep 27 '22 18:09

mre


One work around is to save your changes and add/remove them after the loop.

For example:

List<Item> toRemove = new LinkedList<Item>();

for(Item it:items){
    if(remove){
        toRemove.add(it);
    }
}
items.removeAll(toRemove);
like image 44
jzd Avatar answered Sep 27 '22 18:09

jzd


A second workaround is to use a collection class whose iterators won't give the exception. For example ConcurrentLinkedQueue, ConcurrentHashMap and so on.

These avoid the need to throw exceptions by providing weaker models of consistency for the iterators. (Of course, you need to understand those models, and decide whether they are suitable for your application.)

They are typically a bit slower than non-concurrent collections, but faster than the synchronized collection wrappers if there is significant contention.

like image 44
Stephen C Avatar answered Sep 28 '22 18:09

Stephen C


If you just want to remove the element from the collection, you can use Iterator instead of Iterable.

Otherwise, what you can do is not to iterate the original collection, but first make a copy of the list. For example if your collection is a list, than you can make a new ArrayList(originaList) and iterate over that. The modification should be done to the original list.

Another alternative which maybe better for your use case, is not to use for-each but the traditional for-.

like image 26
nanda Avatar answered Sep 28 '22 18:09

nanda