Fail-fast and Fail-safe iterators in java

Iterators are used to iterate or traverse over collections in java. The iterators can be fail-fast and fail-safe.
Fail-fast iterators throw exceptions at runtime (called the ConcurrentModificationException) if the collection is being modified while iterating over it.
Fail-safe iterators are those which do not throw exception if being modified while iterating because they work over the clone of the collection rather than working on the actual collection.

Iterator which iterate on HashMap, ArrayList classes are some examples of fail-fast Iterator.
Iterator which iterate on ConcurrentHashMap, CopyOnWriteArrayList classes are examples of fail-safe Iterator.

Understand with an Example !

1. Example of Fail-fast iterator

import java.util.ArrayList;
import java.util.Iterator;

public class FailFastIteratorTest {

public static void main(String[] args) {
	ArrayList<String> list = new ArrayList<>();
	list.add("john1");
	list.add("john2");
	list.add("john3");
	list.add("john4");
	list.add("john5");

	System.out.println(list);

	Iterator<String> iterator = list.iterator();
	while (iterator.hasNext()){
		if(iterator.next().equals("john3"))
		{
			list.remove("john3");
		}
	}
	System.out.println(list);
 }
}

OUTPUT

[john1, john2, john3, john4, john5]
Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
	at java.util.ArrayList$Itr.next(ArrayList.java:859)

Problem

The problem here is that you are trying to remove an element “john3” from the list while iterating over it therefore this will lead to ConcurrentModificationException.

How to overcome it ?

So instead of list.remove(“john3”) use iterator.remove() method in the condition

while (iterator.hasNext()){
	if(iterator.next().equals("john3"))
	{
		iterator.remove();
	}
}

OUTPUT

[john1, john2, john3, john4, john5]
[john1, john2, john4, john5]

Using iterator’s remove() method you will not get any such Exception.

Important Fact :

  1. If you wish to use iterators for traversing a collection and then you intend to remove elements from that collection while iteration, then prefer using iterators remove() method as it doesn’t throw ConcurrentModificationException.
  2. There is another way to avoid exception, use fail-safe iterator collections instead, we will look into it below.

2. Example of Fail-safe iterator

As we read earlier, the fail-safe iterators do not throw concurrent modification exception because they work or iterate on the clone of the collection and not
on the actual.

But, There are a couple of drawbacks:

  1. Fail safe iterators does not always guarantee updated data, after the iterator is made if any modification is done on the collection will not reflect in the iterator as it works on the clone.
  2. One overhead is of memory and time used in creating a clone of collection to work on.

I. Example of CopyOnWriteArrayList :

import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class FailSafeIteratorTest {

    public static void main(String[] args) {

        List<String> list = new CopyOnWriteArrayList<>();
        list.add("john1");
        list.add("john2");
        list.add("john3");
        list.add("john4");
        list.add("john5");

        System.out.println(list);

        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            if (iterator.next().equals("john3")) {
                list.remove("john3");
            }
        }
        System.out.println(list);
    }
}

OUTPUT

[john1, john2, john3, john4, john5]
[john1, john2, john4, john5]

Here you will observe, on using fail safe iterator on CopyOnWriteArrayList it will not throw any exception.

II. Example of ConcurrentHashMap :

import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;

public class FailSafeIteratorTest {

    public static void main(String[] args) {

        ConcurrentHashMap<Integer,String> map = new ConcurrentHashMap<>();
        map.put(1,"one");
        map.put(2,"two");
        map.put(3,"three");
        map.put(4,"four");

        System.out.println(map);

        Iterator<Integer> iterator = map.keySet().iterator();
        while (iterator.hasNext()) {
            int key = iterator.next();
            System.out.println(key + " : " + map.get(key));
            map.put(5,"five");
        }
        System.out.println(map);
    }
}

OUTPUT

{1=one, 2=two, 3=three, 4=four}
1 : one
2 : two
3 : three
4 : four
5 : five
{1=one, 2=two, 3=three, 4=four, 5=five}

Here you will observe, on using fail safe iterator on ConcurrentHashMap it will not throw any exception.

3. Difference between Fail-fast and Fail-safe iterators

Fail-fast IteratorFail-safe Iterator
This kind of iterator throws ConcurrentModificationException when iterating over a collection.This kind of iterator does not throw Exception when iterating over a collection.
It iterates on the original collection.It iterates over the copy of original collection and not on the actual collection.
There is no extra memory and time overhead like fail safe iterators as they operate on actual collection.It has an overhead of extra memory and time as it works over the copy of actual collection.
Examples are HashMap, ArrayList.Examples are ConcurrentHashMap, CopyOnWriteArrayList

4. How Iterators work internally ?

Initially in the internal implementation a variable called expectedModCount is equal to modCount which is zero.

int expectedModCount = modCount;

If there is any change done in the collection, the modCOunt will change and then an exception is thrown, by calling a method checkForComodification().

final void checkForComodification() {
     if (modCount != expectedModCount)
	throw new ConcurrentModificationException();
}

Summary

In this article we learnt about Fail-fast and Fail-safe iterators, we also learnt them with examples, it’s differences and internal working.
Hope you liked the article !


Leave a Comment