This post shows show to solve the problem of java.util.ConcurrentModificationException
for ArrayList
.
The error message looks like the following:
Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(Unknown Source) at java.util.ArrayList$Itr.next(Unknown Source) ... ...
The Problem
You may want to iterate through an ArrayList
, and delete some element under some certain condition. For example, the following code looks reasonable:
List<String> list = new ArrayList<String>(); list.add("A"); list.add("B"); list.add("C"); for (String s : list) { if (s.equals("B")) { list.remove(s); } } |
Running the code actually will result in the following exception:
Solution 1
Iterator
can be used to solve this problem. Iterators
allow the caller to remove elements from the underlying collection during the iteration.
Iterator<String> iter = list.iterator(); while(iter.hasNext()){ String str = iter.next(); if( str.equals("B")){ iter.remove(); } } |
Solution 2
Instead of ArrayList
, CopyOnWriteArrayList
can be used to solve the problem. CopyOnWriteArrayList
is a thread-safe variant of ArrayList
in which all mutative operations (add, set, and so on) are implemented by making a fresh copy of the underlying array.
List<String> list = new CopyOnWriteArrayList<String>(); list.add("A"); list.add("B"); list.add("C"); for (String s : list) { if (s.equals("B")) { list.remove(s); } } |
This is the same for other data structures, such as HashSet, LinkedList, etc.
I solved with CopyOnWriteArrayList. thanks so much
This is not true:
“The above code is fine, because they do not use array as the underlining data structure.”
In each of collection is a counter which indicate if collection has been changed (it structure – added or removed element not replaced). If structure of collection will change we will get exception 🙂
I added 2 more elements into the LinkedList and let the remaining codes unchanged.
It did throw “java.util.ConcurrentModificationException”
why ?
Your suggestion to use “CopyOnWriteArrayList” is brilliantly helpful. I’m exploring it’s use, and it is looking good so far 🙂 Plus I need to crack open my well-worn copy of Brian Goetz’s classic work on concurrency (JCIP) for a refresher…. Thank you!