72. Iterator and ConcurrentModificationException
Iterator allows safe traversal and removal; ListIterator adds bidirectional traversal; modifying a collection while iterating via for-each throws ConcurrentModificationException โ use iterator.remove() or removeIf() instead.
Explanation
Java's fail-fast iterators (for ArrayList, HashMap, etc.) maintain a modCount counter that increments on every structural modification. The iterator checks modCount on each next() call; if it doesn't match the value captured at iterator creation, ConcurrentModificationException is thrown. This is a best-effort safety check, not guaranteed under concurrent access.
Safe removal during iteration: use Iterator.remove() โ it removes the most recently returned element and updates modCount. The enhanced for-each loop provides no access to the iterator, so you cannot call remove(). Use iterator.remove() via an explicit Iterator, or Collection.removeIf(predicate) (Java 8+) for bulk removal.
ListIterator<E> (for List implementations) adds: hasPrevious(), previous(), add(e) (insert at cursor), set(e) (replace last returned), nextIndex(), previousIndex().
Example
import java.util.*;
public class IteratorDemo {
public static void main(String[] args) {
List<Integer> nums = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6));
// ConcurrentModificationException trap
try {
for (Integer n : nums) {
if (n % 2 == 0) nums.remove(n); // WRONG: CME!
}
} catch (ConcurrentModificationException e) {
System.out.println("CME thrown โ cannot remove via for-each");
}
// CORRECT: Iterator.remove()
nums = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6));
Iterator<Integer> it = nums.iterator();
while (it.hasNext()) {
if (it.next() % 2 == 0) it.remove(); // safe!
}
System.out.println("Odds only: " + nums); // [1, 3, 5]
// CORRECT (cleaner): removeIf
nums = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6));
nums.removeIf(n -> n % 2 == 0);
System.out.println("removeIf odds: " + nums); // [1, 3, 5]
// ListIterator: bidirectional, add, set
List<String> words = new ArrayList<>(List.of("a", "b", "c"));
ListIterator<String> li = words.listIterator();
while (li.hasNext()) {
String w = li.next();
li.set(w.toUpperCase()); // replace in-place
}
System.out.println("Uppercased: " + words); // [A, B, C]
// Backward traversal
while (li.hasPrevious()) {
System.out.print(li.previous() + " ");
}
System.out.println(); // C B A
}
}