Fail-Fast vs Fail-Safe Iterators in Java
Introduction
Iterators in Java allow traversal of collections. But when collections are modified during iteration, behavior differs. Some iterators throw exceptions immediately (fail-fast), while others tolerate modifications by working on a snapshot (fail-safe). Understanding this difference is crucial for writing robust code and answering interview questions.
Fail-Fast Iterators
Fail-fast iterators operate directly on the collection. If the collection is structurally modified during iteration (other than via the iteratorβs own remove()), they throw a ConcurrentModificationException.
import java.util.*;
public class FailFastExample {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
Iterator<String> it = list.iterator();
while(it.hasNext()) {
System.out.println(it.next());
list.add("D"); // Structural modification
}
}
}
// Output: ConcurrentModificationException
Fail-Safe Iterators
Fail-safe iterators work on a snapshot of the collection. Modifications during iteration do not affect the iterator and no exception is thrown. They are typically found in concurrent collections.
import java.util.concurrent.*;
public class FailSafeExample {
public static void main(String[] args) {
ConcurrentHashMap<Integer, String> map = new ConcurrentHashMap<>();
map.put(1, "A");
map.put(2, "B");
Iterator<Integer> it = map.keySet().iterator();
while(it.hasNext()) {
System.out.println(it.next());
map.put(3, "C"); // Modification allowed
}
}
}
// Output: Iterates safely without exception
Comparison Table
| Aspect | Fail-Fast Iterator | Fail-Safe Iterator |
|---|---|---|
| Collections | Non-concurrent (ArrayList, HashMap, HashSet) | Concurrent (ConcurrentHashMap, CopyOnWriteArrayList) |
| Modification Handling | Throws ConcurrentModificationException | No exception, works on snapshot |
| Visibility of Changes | Changes visible only if done via iterator | Changes not visible during iteration |
| Performance | Faster (no cloning overhead) | Slower (snapshot/copy overhead) |
| Use Case | Single-threaded environments | Multi-threaded environments |
Flowchart Diagram
Interview-Ready Notes
- Key Difference: Fail-Fast detects concurrent modifications and fails immediately; Fail-Safe tolerates modifications by iterating over a snapshot.
- Analogy: Fail-Fast is like reading a live document β if someone edits it while youβre reading, you get an error. Fail-Safe is like reading a photocopy β even if the original changes, your copy remains consistent.
- Best Practice: Use Fail-Fast in single-threaded contexts for performance. Use Fail-Safe in concurrent contexts to avoid exceptions.
- Common Question: βWhy does HashMap iterator fail fast?β β Because it directly accesses the internal structure and uses a modification count to detect changes.
- Follow-Up: βWhy is ConcurrentHashMap iterator fail-safe?β β Because it iterates over a snapshot of the data, ensuring safe traversal in multi-threaded environments.
Conclusion
Fail-Fast and Fail-Safe iterators embody two different philosophies: strict detection vs tolerant safety. Knowing when to use each is crucial for designing robust Java applications and for acing interview questions on concurrency and collections.