Skip to content
java.util.ConcurrentModificationException

java.util.ConcurrentModificationException

DodaTech 3 min read

ConcurrentModificationException fires when you modify a collection while iterating it. Java’s fail-fast iterators detect this and stop to prevent data corruption.

What It Means

You have a loop (typically a for-each loop) that’s iterating over a List, Set, or Map, and somewhere inside the loop body you add or remove elements from that same collection. The iterator detects the modification and throws immediately to prevent undefined behavior.

Why It Happens

  • You call list.remove() inside a for-each loop.
  • You call list.add() while iterating with an iterator.
  • One thread modifies a collection while another thread iterates over it.
  • You use map.put() or map.remove() inside a loop over map.keySet().
  • You’re using a sublist and modify the parent list.

How to Fix It

1. Use iterator.remove() instead of collection.remove()

List<String> names = new ArrayList<>(List.of("Alice", "Bob", "Charlie"));

// BUG: ConcurrentModificationException
for (String name : names) {
    if (name.equals("Bob")) {
        names.remove(name);  // throws
    }
}

// FIX: use iterator directly
Iterator<String> it = names.iterator();
while (it.hasNext()) {
    String name = it.next();
    if (name.equals("Bob")) {
        it.remove();  // safe — iterator's own method
    }
}

2. Collect removals and apply after the loop

List<String> names = new ArrayList<>(List.of("Alice", "Bob", "Charlie"));
List<String> toRemove = new ArrayList<>();

for (String name : names) {
    if (name.equals("Bob")) {
        toRemove.add(name);
    }
}

names.removeAll(toRemove);  // modify after iteration

3. Use removeIf (Java 8+)

names.removeIf(name -> name.equals("Bob"));

This single line does the iteration and removal safely.

4. Use CopyOnWriteArrayList for concurrent access

import java.util.concurrent.CopyOnWriteArrayList;

List<String> safeList = new CopyOnWriteArrayList<>(List.of("Alice", "Bob"));

// Safe to modify during iteration
for (String name : safeList) {
    if (name.equals("Bob")) {
        safeList.remove(name);
    }
}

CopyOnWriteArrayList creates a fresh copy on every mutation, so iteration sees a consistent snapshot.

5. For Maps, iterate over entrySet and use iterator

Map<String, Integer> scores = new HashMap<>();
scores.put("Alice", 90);
scores.put("Bob", 85);

// FIX: use iterator on entrySet
Iterator<Map.Entry<String, Integer>> entryIt = scores.entrySet().iterator();
while (entryIt.hasNext()) {
    Map.Entry<String, Integer> entry = entryIt.next();
    if (entry.getValue() < 60) {
        entryIt.remove();  // safe
    }
}
Does ConcurrentModificationException always mean multiple threads?
No. The name is misleading — it commonly happens in single-threaded code when you modify a collection inside a for-each loop. The “concurrent” refers to the collection being modified at the same time as it is being iterated, regardless of threading.
Why doesn't the exception happen immediately?
The iterator checks for modification on the next next() call, not when the modification occurs. This is why you can sometimes add one element without error — the exception fires on the next iteration, not at the point of the add() or remove().
Can I use a regular for loop with index to avoid this?
Yes, with indexed loops you can safely remove elements because you control the index. However, you must adjust the index after removal: for (int i = 0; i < list.size(); i++) { if (condition) { list.remove(i--); } }.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro