java.util.ConcurrentModificationException
This exception means you’re modifying a collection (adding, removing, or replacing elements) while iterating over it. Despite the name, this doesn’t require multiple threads — a single-threaded for-each loop that calls list.remove() is enough to trigger it.
What causes this
Java’s ArrayList, HashMap, and most standard collections use a fail-fast iterator. The iterator tracks a modification count. If the collection is structurally modified outside the iterator, the counts go out of sync and the iterator throws ConcurrentModificationException on the next call to next().
// ❌ Classic trigger — modifying during for-each
for (String item : list) {
if (item.equals("remove")) {
list.remove(item); // ConcurrentModificationException!
}
}
The enhanced for-each loop uses an iterator internally, but list.remove() bypasses it and modifies the collection directly.
Fix 1: Use Iterator.remove()
The iterator’s own remove() method is the safe way to remove elements during iteration:
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String item = it.next();
if (item.equals("remove")) {
it.remove(); // Safe — iterator knows about this removal
}
}
This works because Iterator.remove() updates the internal modification count, keeping the iterator in sync.
Fix 2: Use removeIf (Java 8+)
For simple removal conditions, removeIf is cleaner and handles the iteration internally:
list.removeIf(item -> item.equals("remove"));
// Works on maps too (via entrySet)
map.entrySet().removeIf(entry -> entry.getValue() == null);
Fix 3: Use a CopyOnWriteArrayList
If you need to iterate and modify from multiple threads, use a concurrent collection:
List<String> list = new CopyOnWriteArrayList<>();
// Safe to iterate and modify concurrently
The trade-off is that every write copies the entire array, so this is only practical for small lists that are read far more often than written.
Fix 4: Use ConcurrentHashMap for maps
// ❌ Regular HashMap — not safe
Map<String, Integer> map = new HashMap<>();
// ✅ Thread-safe iteration and modification
Map<String, Integer> map = new ConcurrentHashMap<>();
map.forEach((key, value) -> {
if (value == 0) {
map.remove(key); // Safe with ConcurrentHashMap
}
});
How to prevent it
- Never call
collection.remove()inside a for-each loop. UseIterator.remove()orremoveIf(). - If you need to add elements during iteration, collect them in a separate list and call
addAll()after the loop. - For multi-threaded access, use
java.util.concurrentcollections (ConcurrentHashMap,CopyOnWriteArrayList) instead of wrapping withCollections.synchronizedList()— the synchronized wrappers still throw this exception if you iterate without external synchronization.