javaiteratorfail-fast

Fail fast iterators in Java


public class Alpha {

    public static void main(String[] args) {
        ArrayList<String> al = new ArrayList<String>();

        al.add("a");
        al.add("b");
        al.add("c");
        al.add("d");
        al.add("e");


        Iterator<String> itr = al.listIterator();
        while(itr.hasNext()){
            al.remove("d"); // Throws a Concurrent Modification @ this line
            if(itr.next().equals("d")){
                //itr.remove();
                al.remove("d"); // No error on this line
            }

        }
        System.out.println(al);

    }

}

In other words, if "al.remove("d") is placed inside the if construct there is no ConcurrentModificationException thrown, where as the same line of code, if placed outside of the if -Construct throws an exception. Kindly explain!


Solution

  • I have added a line (line 13) and some comment line numbers (line 18, line 19 & line 21).

    Now, ConcurrentModidificationexception is not thrown at line 18, but it is thrown at line 19. But yeah it is thrown due to execution of line 18.

    Also, I believe that you are using the code at lines 18 & 21 one at a time. They do not occur simultaneously in your code.

    import java.util.*;
    
    public class HelloWorld{
    
    public static void main(String []args){
        ArrayList<String> al = new ArrayList<String>();
    
        al.add("a");
        al.add("b");
        al.add("c");
        al.add("d");
        al.add("e");
        al.add("f"); // line 13
    
    
        Iterator<String> itr = al.listIterator();
        while(itr.hasNext()){
            al.remove("d"); // line 18
            if(itr.next().equals("d")){  // line 19
                //itr.remove();
                al.remove("d"); // line 21
            }
    
        }
        System.out.println(al);
    }
    }
    

    Lets comment line 13. So this is basically your code with some extra comments.

    If we check the implementation of next() of iterator we come to know that it checks for any modification (and thereby throwing the CoMo) at the very beginning. After that it just returns the element.

    So if we remove the element from the list without using the iterator at line 18, this gets detected at following next() call. But if you remove the element (at line 21; line 18 is commented by now) after next() method, CoMo will be detected only at the subsequent next(). What happens in your case is that we run out of element after printing 'e'. So we never executed subsequent next(), and didn't get the exception.

    Now, if we uncomment the line 13 (which adds a new element), then we will get ConcurrentModidificationexception at line 19, i.e. when next next() is executed. This proves that we will get the CoMo Exception, it just that we will get it after one more iteration.