Tutorials Logic, IN info@tutorialslogic.com

ConcurrentModificationException in Java Fix: Causes, Fixes, Examples & Interview Tips

What is This Error?

The ConcurrentModificationException is thrown when a collection is modified while it is being iterated using an iterator or enhanced for-each loop. Java's fail-fast iterators detect structural modifications and throw this exception to prevent unpredictable behavior.

Common Causes

  • Adding or removing elements from a list while iterating with for-each
  • Modifying a collection in a multi-threaded environment without synchronization
  • Calling list.remove() instead of iterator.remove() during iteration
  • Modifying a Map's entrySet while iterating over it
  • Nested iteration where inner loop modifies the outer collection

Quick Fix (TL;DR)

Quick Solution

Quick Solution
// ❌ Problem
for (String item : list) {
    if (item.equals("remove")) list.remove(item); // ConcurrentModificationException!
}

// ✅ Solution 1: Use Iterator
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    if (it.next().equals("remove")) it.remove(); // Safe!
}

// ✅ Solution 2: removeIf (Java 8+)
list.removeIf(item -> item.equals("remove"));

Common Scenarios & Solutions

Problem

Problem
List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
for (Integer num : numbers) {
    if (num % 2 == 0) {
        numbers.remove(num); // ❌ ConcurrentModificationException!
    }
}

Solution

Solution
List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));

// ✅ Option 1: removeIf (cleanest)
numbers.removeIf(num -> num % 2 == 0);

// ✅ Option 2: Iterator
Iterator<Integer> it = numbers.iterator();
while (it.hasNext()) {
    if (it.next() % 2 == 0) it.remove();
}

// ✅ Option 3: Collect to remove list
List<Integer> toRemove = numbers.stream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList());
numbers.removeAll(toRemove);

// ✅ Option 4: Stream filter (creates new list)
numbers = numbers.stream()
    .filter(n -> n % 2 != 0)
    .collect(Collectors.toList());

Solution

Solution
// ✅ Use CopyOnWriteArrayList for thread-safe iteration
List<String> list = new CopyOnWriteArrayList<>(Arrays.asList("a", "b", "c"));
for (String s : list) {
    list.add("d"); // Safe "” iterates over snapshot
}

// ✅ Or use synchronized block
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
synchronized (syncList) {
    for (String s : syncList) {
        // Safe iteration
    }
}

Problem

Problem
Map<String, Integer> map = new HashMap<>();
map.put("a", 1); map.put("b", 2); map.put("c", 3);
for (Map.Entry<String, Integer> entry : map.entrySet()) {
    if (entry.getValue() < 2) map.remove(entry.getKey()); // ❌ CME!
}

Solution

Solution
// ✅ Use Iterator on entrySet
Iterator<Map.Entry<String, Integer>> it = map.entrySet().iterator();
while (it.hasNext()) {
    if (it.next().getValue() < 2) it.remove();
}

// ✅ Or use entrySet().removeIf (Java 8+)
map.entrySet().removeIf(e -> e.getValue() < 2);

Best Practices to Avoid This Error

  • Use removeIf() - Cleanest way to remove elements conditionally (Java 8+)
  • Use Iterator.remove() - Safe removal during iteration
  • Collect then remove - Build a removal list, then call removeAll()
  • Use CopyOnWriteArrayList - For thread-safe iteration with modifications
  • Use Stream.filter() - Creates a new collection without modifying the original
  • Use ConcurrentHashMap - Thread-safe map that allows concurrent modification
  • Avoid modifying collections in nested loops - Use separate data structures

Related Errors

Frequently Asked Questions

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).

Fail-fast iterators (ArrayList, HashMap) throw CME on modification. Fail-safe iterators (CopyOnWriteArrayList, ConcurrentHashMap) work on a copy and don't throw CME but may not reflect recent changes.

Use list.removeIf() for simple conditions, Iterator.remove() for manual iteration, or collect elements to remove and call removeAll() after the loop.

Yes, if one thread iterates while another modifies the collection. Use CopyOnWriteArrayList, ConcurrentHashMap, or synchronize access to prevent this.

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.