DEV Community

loading...

What are Fail Fast Iterators in Java Collections?

priyankanandula
@AboutMe("Love to CODE")
・4 min read

Signed in as @priyankanandula

Hello, Developers hope you guys are doing great 😃.Today I came up with an interesting and important concept in Java Collections, as well as in interviews. I hope you enjoy it.

Do you know what was the issue with using the for-loop to iterate the Collection objects ❓

image

Let me explain this to you in such case 👇.

Let's take a look at the following code

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

public class IteratorDemo {


    private static void arrayListDemo() {
        List<Integer> list=new ArrayList<>();
        list.add(5);
        list.add(6);
        list.add(7);
        list.add(9);
        for(int element:list) {

            System.out.println("element : "+element);

            if(element==6) {

                list.remove(Integer.valueOf(7));
            }
        }

    }

    public static void main(String[] args) {
        arrayListDemo();

    }

}
Enter fullscreen mode Exit fullscreen mode

OUTPUT :

element : 5
element : 6
Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
    at java.util.ArrayList$Itr.next(Unknown Source)
    at IteratorDemo.arrayListDemo(IteratorDemo.java:14)
    at IteratorDemo.main(IteratorDemo.java:27)
Enter fullscreen mode Exit fullscreen mode

image

It was printed up to element 6, after which the element in the following index is 7, and we have put a condition to remove that element from the list if it is 7 and here it was thrown
java.util.ConcurrentModificationException

NOTE : However, we can do replacement operations such as set method, and this exception will never be thrown.

Root Cause :

Internally, for-each statement, it invokes the iterator function for the given object and iterates over the elements using the instance obtained by the iterator.

The iterator, which is internally written, generates the concurrent modification exception.

The iterator does not allow us to make any concurrent structural changes (removing/adding) to the underlying ArrayList.

Such Iterators which gives a concurrent modification exception are called fail-fast Iterator.

Solution :

The solution here is to use Iterator interface and to access an instance of iterator we need to invoke the iterator method which is declared in the Iterable interface.

Collection interface already extends the Iterable interface and collection implementations like ArrayList, HashSet.. implements the Iterator method.

public interface Collection
extends Iterable{..}

Collection interface is saying that its elements can be iterated by extending the Iterable.

image

The `java.lang.Iterable` interface provides the following methods:
  • iterator() : We can iterate the elements of Java Iterable by obtaining the Iterator from it using the iterator() method.
  • forEach​(Consumer<? super T> action) : Performs the given action for each element of the Iterable until all elements have been processed or the action throws an exception.
  • spliterator() : The Spliterator interface, can be used for traversing and partitioning sequences. It's a base utility for Streams, especially parallel ones.

image

The `java.util.Iterator` interface provides the following methods:
  • boolean hasNext() - Returns true if the iteration has more elements.
  • E next() - Returns the next element in the iteration.
  • void remove() - Removes from the underlying collection the last element returned by the iterator (optional operation).
  • forEachRemaining(Consumer<? super E>action) - Performs the given action on each of the element until and unless all the elements have been processed or unless an exception is thrown by the action.

Now, using the Iterator interface, we'll rewrite the code to remove the element.

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


public class IteratorDemo {


    private static List<Integer> arrayListDemo() {
        List<Integer> list=new ArrayList<>();
        list.add(5);
        list.add(6);
        list.add(7);
        list.add(9);


        return list;
    }

    private static void iteratorDemo(List<Integer> list1) {
        System.out.println("\nInside iteratorDemo ... ");

        Iterator<Integer> iterator = list1.iterator();
        while (iterator.hasNext()) {
            int element = iterator.next();
            System.out.println("element: " + element);

            if (element == 9) {
                iterator.remove();

            }
        }
        System.out.println("List After removing the element " + list1);


    }

    public static void main(String[] args) {
        List<Integer> list1 = arrayListDemo();
        iteratorDemo(list1);
    }
}

Enter fullscreen mode Exit fullscreen mode

OUTPUT :


Inside iteratorDemo ... 
element: 5
element: 6
element: 7
element: 9
List After removing the element [5, 6, 7]
Enter fullscreen mode Exit fullscreen mode

Yo 🤘 ! It doesn't throw any exceptions anymore.

image

NOTE : The invocation of remove method must be preceded by the invocation of next() method otherwise it will throw an exception.Because the remove method will removes the element that was returned by the next() method.

For Example : Sample Code
while (iterator.hasNext()) {
            int element = iterator.next();
            System.out.println("element: " + element);

            if (element == 9) {
                iterator.remove();
                iterator.remove();
            }
        }
Enter fullscreen mode Exit fullscreen mode

OUTPUT

Inside iteratorDemo ... 
element: 5
element: 6
element: 7
element: 9
Exception in thread "main" java.lang.IllegalStateException
    at java.util.ArrayList$Itr.remove(Unknown Source)
    at IteratorDemo.iteratorDemo(IteratorDemo.java:30)
    at IteratorDemo.main(IteratorDemo.java:40)
Enter fullscreen mode Exit fullscreen mode

It will throw an exception at the second remove method because it has to be preceded by next() method only.


Generally the use case of this scenario like removing during the iteration could be that you may have retrieved a list of elements form the database and now you want to remove some of them which meets certain criteria.

That's it for today, guys. I hope you learned something new.

image

This is priyanka nandula signing off...

Discussion (0)