ConcurrentModificationException happens when a collection is structurally changed while it is being iterated in a way the iterator does not allow. The word concurrent can be confusing: it can happen in a single thread as well as in multi-threaded code.
The most common beginner cause is removing from an ArrayList inside an enhanced for loop. The iterator expects the collection structure to stay stable unless the iterator itself performs the removal.
The fix is to choose the correct removal pattern: Iterator.remove(), removeIf(), collecting changes first, or using a concurrent collection when multiple threads are involved.
In real projects, this exception often appears after a helper method is added inside an existing loop. Review not only the loop body but also every method called inside the loop, because the hidden modification may happen there.
If removal order matters, prefer collecting target items first and removing after iteration. That keeps the loop readable and avoids changing the structure while the iterator is active.
Java collection iterators are fail-fast. They keep an internal modification count and compare it with the collection modification count. If the collection changes unexpectedly, the iterator detects it and throws ConcurrentModificationException.
This protects you from silently skipping elements or reading inconsistent data. It is a debugging signal that your iteration and modification logic need to be separated or coordinated.
If you need to remove while iterating, use an explicit Iterator and call iterator.remove(). If the condition is simple, removeIf() is shorter and easier to read.
For complex updates, build a second list of items to remove, finish the loop, then call removeAll(). In multi-threaded programs, use CopyOnWriteArrayList, ConcurrentHashMap, synchronization, or another design that avoids unsafely sharing mutable collections.
Find the loop in the stack trace and search for add, remove, clear, or put calls that affect the same collection. Also check methods called inside the loop, because the modification may be hidden in a helper method.
If the issue appears only sometimes, inspect thread access. A background thread, timer, event listener, or request handler may be changing the collection while another part of the program reads it.
For a collection owned by one thread, keep mutation inside the iterator operation or defer changes until iteration ends. This preserves a clear order and usually needs no concurrent collection.
For genuinely shared state, define the consistency required by readers. CopyOnWriteArrayList suits read-heavy, small collections because every write copies its backing array. ConcurrentHashMap supports concurrent access with weakly consistent iteration, but compound decisions should use atomic methods such as compute, merge, or remove with an expected value.
List<String> names = new ArrayList<>(List.of("Ana", "Bob", "Amit"));
for (String name : names) {
if (name.startsWith("A")) {
names.remove(name); // may throw ConcurrentModificationException
}
}
List<String> names = new ArrayList<>(List.of("Ana", "Bob", "Amit"));
names.removeIf(name -> name.startsWith("A"));
System.out.println(names); // [Bob]
It's thrown when a collection's structure is modified (add/remove) while iterating over it with an iterator or for-each loop. Java's fail-fast iterators detect this and throw the exception.
Yes! You can modify element values (e.g., list.set(index, newValue)) without causing CME. The exception only occurs when you add or remove elements (structural modifications).
ArrayList and HashMap iterators normally fail fast after an unexpected structural change. CopyOnWriteArrayList iterates over a snapshot, while ConcurrentHashMap iterators are weakly consistent and may reflect some updates. ConcurrentHashMap does not iterate over a copied map.
Explore 500+ free tutorials across 20+ languages and frameworks.