java.util.ConcurrentModificationException
ID: java/concurrentmodificationexception
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| 17 | active | — | — | — |
Root Cause
ConcurrentModificationException is thrown when a collection is structurally modified while being iterated, either from the same thread (modifying during for-each loop) or from another thread without proper synchronization.
genericWorkarounds
-
95% success Use Iterator.remove() for single-threaded removal during iteration, or use Collection.removeIf() for predicate-based removal
1. For removing elements while iterating: replace the for-each loop with an explicit Iterator and call iterator.remove(). 2. For simpler cases, use collection.removeIf(predicate) which handles the iterator internally. 3. For adding elements during iteration, copy the collection first: new ArrayList<>(original) and iterate over the copy while modifying the original.
-
90% success Use ConcurrentHashMap or CopyOnWriteArrayList for multi-threaded access
1. For Map: replace HashMap with ConcurrentHashMap. Its iterators are weakly consistent and never throw ConcurrentModificationException. 2. For List with mostly reads: replace ArrayList with CopyOnWriteArrayList. It creates a fresh copy on every write, so iterators see a snapshot. 3. For List with frequent writes: use synchronized blocks around iteration or ConcurrentLinkedDeque for queue-like access patterns. 4. For Stream operations, use parallelStream() with thread-safe collectors instead of manual iteration.
Dead Ends
Common approaches that don't work:
-
Wrapping the collection with Collections.synchronizedList() and iterating without external synchronization
75% fail
Collections.synchronizedList() only synchronizes individual method calls. Iteration requires holding the lock for the entire duration of the loop. Without a synchronized block around the entire iteration, another thread can modify the list between hasNext() and next() calls.
-
Using collection.remove() inside a for-each loop instead of iterator.remove()
95% fail
The enhanced for-each loop uses an iterator internally. Calling collection.remove() modifies the collection's modCount without updating the iterator's expectedModCount, which triggers the ConcurrentModificationException on the next iterator operation.