In Java, many collections (like ArrayList
, HashMap
, etc.) have fail-fast iterators. This means that if the collection is structurally modified after the iterator is created, the iterator will throw a:
java.util.ConcurrentModificationException
✅ What counts as a structural modification?
- Add or remove elements directly via the collection itself.
- Clear the collection.
- Any change that alters the size or structure of the collection.
🧠 Note: Changes through the iterator itself (e.g., iterator.remove()
) do not cause failure — they’re considered safe.
🔥 Why does it fail fast?
- To catch concurrent modifications early.
- To avoid unpredictable behavior if a collection changes while it’s being iterated over.
- To make bugs easier to diagnose by failing at the moment of misuse.
🧪 Example: ArrayList Fail-Fast Behavior
List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("Go");
Iterator<String> iterator = list.iterator();
list.add("Rust"); // structural modification after iterator created
while (iterator.hasNext()) {
System.out.println(iterator.next()); // throws ConcurrentModificationException
}
✅ Safe way using iterator’s own method
List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("Go");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String value = iterator.next();
if (value.equals("Python")) {
iterator.remove(); // Safe way to remove during iteration
}
}
System.out.println(list); // [Java, Go]
🧠 Under the Hood: modCount
Java collections use an internal variable called modCount
(modification count):
- When you structurally modify the collection,
modCount
increases. - The iterator captures the modCount at the time it was created.
- If
modCount
has changed unexpectedly during iteration, it throws aConcurrentModificationException
.
💬 Common Mistakes to Watch For
- Modifying a collection inside a
for-each
loop: javaCopyEdit
for (String item : list) {
list.remove(item); // ❌ throws ConcurrentModificationException
}
Fix: Use an explicit Iterator
with remove()
.
🛡️ How to handle it?
- Copy the collection before iterating (if modification is needed).
- Use
CopyOnWriteArrayList
or other concurrent collections in multithreaded environments. - Or use iterator’s
remove()
method for safe structural changes.