DEV Community

realNameHidden
realNameHidden

Posted on

What Is the Difference Between Fail-Safe and Fail-Fast Iterators?

Overview of Iterators in Java

In Java, iterators are objects that allow sequential access to elements in a collection (e.g., ArrayList, HashSet) without exposing the underlying structure. The key difference between fail-safe and fail-fast iterators lies in how they handle concurrent modifications to the collection during iteration. Fail-fast iterators detect such changes and throw an exception immediately, while fail-safe iterators do not.

This behavior is crucial for multithreaded applications or when modifying a collection while iterating over it.

Fail-Fast Iterators

Definition: These iterators throw a ConcurrentModificationException as soon as they detect that the underlying collection has been structurally modified (e.g., elements added, removed, or resized) since the iterator was created.

How it works: Fail-fast iterators maintain a “modCount” (modification count) in the collection. Each structural change increments this count. During iteration, the iterator checks if the current modCount matches the one at creation — if not, it throws the exception.

Examples: Iterator and ListIterator from ArrayList, HashMap, HashSet, etc.

Use case: Ideal for single-threaded environments where you want to enforce immutability during iteration to prevent subtle bugs.

Pros: Detects errors early, promoting safer code.

Cons: Not suitable for concurrent access; even safe operations like remove() via the iterator itself can trigger it if not handled properly.

Fail-Safe Iterators

Definition: These iterators work on a copy of the collection or use a mechanism that allows modifications without throwing exceptions. They don’t detect concurrent changes.

How it works: Instead of iterating over the original collection, they often create a snapshot (clone) at the start of iteration. Modifications to the original collection don’t affect the iterator’s view.

Examples:
CopyOnWriteArrayList (from java.util.concurrent package).
ConcurrentHashMap’s keySet or entrySet iterators.

Use case: Perfect for multithreaded scenarios where one thread iterates while others modify the collection.

Pros: Thread-safe and allows concurrent modifications without interruptions.

Cons: Higher memory and performance overhead due to copying (e.g., CopyOnWriteArrayList copies the entire array on write).

Example Code Snippet

To illustrate, consider this simple example with an ArrayList (fail-fast):

import java.util.*;

public class IteratorExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
        Iterator<String> it = list.iterator();

        while (it.hasNext()) {
            String item = it.next();
            if (item.equals("B")) {
                list.remove(item);  // Concurrent modification!
            }
        }
        // Output: Throws ConcurrentModificationException
    }
}
Enter fullscreen mode Exit fullscreen mode

For a fail-safe version, replace ArrayList with CopyOnWriteArrayList — the removal won’t throw an exception, and iteration completes on the snapshot.

In summary, choose fail-fast for robustness in controlled environments and fail-safe for concurrency. Always check the documentation for specific collection behaviors, as not all iterators strictly follow these patterns.

Top comments (0)