Collections Frameworkmedium

Fail-Fast Iterators

Most java.util collection iterators are fail-fast — if the collection is structurally modified while iterating (add/remove), they throw ConcurrentModificationException on the next iterator operation.

Memory anchor

Fail-fast iterator = a librarian reading a shelf aloud. If someone sneaks in and removes a book mid-reading, the librarian screams (ConcurrentModificationException). Only the librarian herself can remove books safely (Iterator.remove()).

Expected depth

Fail-fast is implemented via a modCount counter — incremented on every structural modification. The iterator captures modCount at creation; each next()/remove() checks if modCount has changed. To safely remove during iteration: use Iterator.remove() (which updates the internal expectedModCount). To safely add during iteration: use ListIterator.add(). For concurrent modification from another thread: use CopyOnWriteArrayList (snapshot semantics, expensive writes) or ConcurrentHashMap's weakly-consistent iterators (no CME, reflects state at some point).

Deep — senior internals

ConcurrentModificationException is a best-effort detection, not a guarantee — the JMM does not guarantee visibility of modCount changes between threads without synchronization, so a concurrent modification may go undetected (especially on multi-core hardware). The Java documentation explicitly warns that it should be used only to detect bugs, not for correctness. CopyOnWriteArrayList creates a new array on every write — O(n) write cost — and its iterators operate on a snapshot, so add/remove from within an iterator loop are silently ignored (the original list is modified, but the iterator sees the old snapshot).

🎤Interview-ready answer

Fail-fast iterators throw ConcurrentModificationException when the collection's structure changes between iterator creation and use. The implementation uses a modCount field — the iterator checks it on each operation. Safe removal requires Iterator.remove(), not Collection.remove(). For multi-threaded scenarios, fail-fast is not a reliable safety mechanism — use ConcurrentHashMap or CopyOnWriteArrayList whose iterators are weakly consistent or snapshot-based respectively.

Common trap

Calling collection.remove(object) inside a for-each loop throws ConcurrentModificationException, but calling Iterator.remove() inside a manual Iterator loop does not — the for-each loop uses an iterator internally, and external remove() increments modCount without updating the iterator's expectedModCount.

Related concepts