Fail Fast and Fail Safe Iterators in Java

Learn via video course
FREE
View all courses
Java Course - Mastering the Fundamentals
Java Course - Mastering the Fundamentals
by Tarun Luthra
1000
5
Start Learning
Java Course - Mastering the Fundamentals
Java Course - Mastering the Fundamentals
by Tarun Luthra
1000
5
Start Learning
Topics Covered

Overview

In Java, iterators are widely used to traverse and manipulate collections like lists, sets, and maps. Two important concepts related to iterators are Fail-Fast and Fail-Safe in java. These concepts refer to different strategies for handling concurrent modifications to a collection while it is being iterated.

Fail-Fast iterators are designed to detect and immediately throw a ConcurrentModificationException if the collection is modified while an iterator is actively iterating over it.

Fail-Safe iterators are designed to operate safely in the presence of concurrent modifications to the collection.

Iterators in Java

An iterator provides a way to access elements of a collection one at a time without exposing the underlying data structure. This abstraction simplifies the process of iterating through various types of collections, such as lists, sets, and maps, in a uniform way. Here's are the types of iterators in Java:

Iterator Interface:

The java.util.Iterator interface is at the core of Java's iteration mechanism. It defines three main methods:

  • boolean hasNext(): Returns true if there are more elements in the collection to iterate over.
  • E next(): Returns the next element in the collection and advances the iterator position.
  • void remove(): Removes the last element returned by next() from the collection.

Iterable Interface:

The java.lang.Iterable interface is implemented by classes that represent collections of objects, such as lists, sets, and maps. It includes a single method:

Iterator iterator(): Returns an iterator over the elements of the collection.

By implementing the Iterable interface, a class can provide an iterator for its elements, making it suitable for use in enhanced for loops and other iteration constructs.

Enhanced For Loop: Java introduced the enhanced for loop (also known as the for-each loop) to simplify iteration over collections. You can use this loop to iterate through any collection that implements the Iterable interface:

Iterator Implementations:

The Java Collections Framework provides iterator implementations for various collection types. Common iterator implementations include:

  • ArrayList Iterator: Used for iterating through ArrayList collections.

  • HashSet Iterator:

    Used for iterating through HashSet collections.

  • HashMap Iterator:

    Used for iterating through HashMap collections.

You can obtain an iterator for a collection using the iterator() method provided by that collection.

Fail Fast in Java

Fail-Fast is a strategy used in Java to handle concurrent modifications to a collection while it is being iterated. The main idea behind Fail-Fast is to detect any changes made to the collection during iteration and throw a ConcurrentModificationException immediately to prevent potential data corruption or unpredictable behavior.

How It Works

  • When an iterator is created for a collection, it usually maintains an internal modification count or a version number that represents the state of the collection at the time the iterator was created.
  • During each iteration step (calling next()), the iterator checks whether the current modification count matches the initial modification count. If they differ, it implies that the collection has been modified by another thread since the iterator was created.
  • If a mismatch is detected, the iterator throws a ConcurrentModificationException to signal that the collection's state has changed unexpectedly, and it's not safe to continue iterating.

Important Points about Fail-Fast Iterators in Java

  • Immediate Detection:

    Fail-Fast iterators aim to detect concurrent modifications as soon as they occur, ensuring that any potential issues are raised immediately during iteration.

  • Safety First:

    The Fail-Fast strategy prioritizes safety over allowing concurrent modifications. It prevents situations where multiple threads might access and modify a collection simultaneously.

Example

Here's an example of using a Fail-Fast iterator with an ArrayList:

Explanation:

  • An ArrayList named list is created and initialized with two elements: Apple and Banana.
  • An iterator is obtained using list.iterator().
  • The code enters a while loop to iterate through the elements of the list using the iterator.
  • The first element Apple is retrieved and printed to the console, resulting in the output:
  • The second element Banana is retrieved and printed to the console, resulting in the output:
  • Inside the loop, there's a conditional check:
    • The condition if(fruit.equals("Banana")) evaluates to true when the iterator is processing the Banana element.
  • Inside the conditional block, a new element Cherry is added to the same list using list.add("Cherry"). This is the point at which the concurrent modification occurs.
  • As a result of the concurrent modification, a ConcurrentModificationException is thrown. The program terminates, and the exception message is printed to the console. The exception message typically includes information about where the modification occurred.

Output:

The output of the code will include an exception stack trace similar to the following:

Fail Safe Iterator in Java

A Fail-Safe iterator is a different strategy used in Java to handle concurrent modifications to a collection while it is being iterated. Unlike Fail-Fast iterators, Fail-Safe iterators do not throw ConcurrentModificationException. Instead, they work on a copy of the original collection or use a snapshot of the data structure. This approach allows for safe iteration without the risk of concurrent modifications affecting the iteration process.

How It Works

  • When a Fail-Safe iterator is created, it typically operates on a snapshot of the collection or a copy of the elements at the time of iterator creation.
  • Any modifications made to the original collection during the iteration process do not affect the iterator since it is working on its copy.
  • Fail-Safe iterators ensure that the original collection remains unchanged during iteration and continue to provide a consistent view of the collection's state as it was when the iterator was created.

Important Points about Fail-Safe Iterators in Java

  • No ConcurrentModificationException:

    Fail-Safe iterators do not throw ConcurrentModificationException when the underlying collection is modified during iteration. This makes them more suitable for scenarios where concurrent modifications are expected or tolerated.

  • Iterate on a Snapshot:

    Fail-Safe iterators provide a snapshot of the collection at the time of iterator creation. This means they are less likely to detect concurrent modifications but provide a consistent view.

Example

Here's an example of using a Fail-Safe iterator with a ConcurrentHashMap:

Explanation:

In this example, the code creates a ConcurrentHashMap, which is designed to work with Fail-Safe iterators. It then creates an iterator for the keys of the map and iterates through them.

During the iteration, a new key-value pair (key3, value3) is added to the map when the iterator is processing the key key2. Unlike Fail-Fast iterators, a Fail-Safe iterator will not throw any exceptions in this scenario. It will continue to iterate over the original keys (key1 and key2) without any issues.

Output:

The output of the code will be:

The key key3 is not included in the iteration since the Fail-Safe iterator works on a snapshot of the collection at the time of iterator creation.

Fail Fast vs Fail Safe Iterator in Java

Let us look at the difference between fail fast and fail safe in java.

AspectFail-Fast IteratorFail-Safe Iterator
Behavior on Concurrent ModificationThrows ConcurrentModificationException immediately if a collection is modified during iteration.Continues iterating on the original collection, typically without throwing exceptions, but may not reflect concurrent modifications.
Exception ThrownConcurrentModificationExceptionNo ConcurrentModificationException is thrown.
Safety PriorityPrioritizes safety by detecting and preventing concurrent modifications to ensure data integrity.Prioritizes allowing concurrent modifications without disrupting the iteration process.
Use CaseSuitable for single-threaded scenarios or situations where detecting concurrent modifications is crucial.Suitable for multi-threaded scenarios where concurrent modifications are expected or tolerated.

FAQs

Q. What is Java's main advantage in application development?

A. Java's main advantage is its platform independence due to the use of the Java Virtual Machine (JVM).

Q. What is the purpose of the "public static void main" method in Java?

A. It's the entry point of a Java program, where execution begins.

Q. What is the difference between == and .equals() in Java when comparing objects?

A. == compares object references, while .equals() compares object content (values).

Conclusion

  • fail fast and fail safe in Java are two different error-handling approaches in Java for dealing with concurrent data structures and multi-threading issues.
  • Fail-fast iterators detect and immediately respond to concurrent modifications during iteration. It is commonly used with non-thread-safe collections and iterators
  • Fail-safe iterators tolerate concurrent modifications during iteration without throwing exceptions. It is commonly used with thread-safe collections and iterators.
  • Fail-fast iterators prioritize safety and data integrity, and it throws ConcurrentModificationException if a collection is modified while another thread is iterating over it.
  • Fail-safe iterators prioritize allowing concurrent modifications without disruption and allow multiple threads to operate on a data structure without throwing exceptions.