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.
// ❌ 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"));
List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
for (Integer num : numbers) {
if (num % 2 == 0) {
numbers.remove(num); // ❌ ConcurrentModificationException!
}
}
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());
// ✅ 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
}
}
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!
}
// ✅ 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);
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.
Explore 500+ free tutorials across 20+ languages and frameworks.