🔧 Error Fixes
· 2 min read
Last updated on

Java ConcurrentModificationException — How to Fix It


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. Use Iterator.remove() or removeIf().
  • 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.concurrent collections (ConcurrentHashMap, CopyOnWriteArrayList) instead of wrapping with Collections.synchronizedList() — the synchronized wrappers still throw this exception if you iterate without external synchronization.