2

I am learning about collection classes in Java. I created an ArrayList and added some values to it.

package LearningJava;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Scanner;

public class Java{

    public static void  main(String args[]) {

        Collection values = new ArrayList();
        values.add(2);
        values.add(3);
        values.add(5);
        values.add(4);

        Iterator itr = values.iterator();
        for(int i = 0 ; i<values.size();i++) {
            System.out.println(itr.next());
        }
    }
}

I also iterated through this ArrayList.

If I add values after creating, the object of iterator throws an exception.

package LearningJava;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Scanner;

public class Java{

    public static void  main(String args[]) {

        Collection values = new ArrayList();
        values.add(2);
        values.add(3);
        values.add(5);
    
        Iterator itr = values.iterator();
        values.add(4);
    
        for(int i = 0 ; i<values.size();i++) {
            System.out.println(itr.next());
        }
    }
} 

It throws a java.util.ConcurrentModificationException. Why can't I add values after creating the object of iterator?

It is only throwing this exception in case of Iterator interface. When I create the object of other classes, it does not throw any exception.

package LearningJava;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Scanner;

public class Java{

    public static void  main(String args[]) {

        Collection values = new ArrayList();
        values.add(2);
        values.add(3);
        values.add(5);
    
         // creating the object of scanner instead of iterator's.
        Scanner input  = new Scanner(System.in);

        values.add(4);

        Iterator itr = values.iterator();
        for(int i = 0 ; i<values.size();i++) {
            System.out.println(itr.next());
        }
    }
}

Here it is not showing any errors. Why is this?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • 2
    Does this answer your question? [Adding elements to a collection during iteration](https://stackoverflow.com/questions/993025/adding-elements-to-a-collection-during-iteration) – Sayan Bhattacharya Aug 13 '22 at 04:39
  • 1
    Note that (at least part of) the state that tracks if the source collection has been concurrently structrually modified is held by the `Iterator` instance (at least as currently implemented). If the source collection is structurally modified _after_ the `Iterator` has been created, then it's possible the `Iterator` will be out-of-date or otherwise "damaged", and so it throws the error. And also note that if you were to create an `Iterator`, structurally modify the collection, and then create a **new** `Iterator` and use that **new** `Iterator` in your loop, then the error would not be thrown. – Slaw Aug 13 '22 at 04:52
  • 1
    When you use an iterator, you should use `hasNext()` instead of a counter, e.g. `for(Iterator itr = values.iterator(); itr.hasNext(); ) { System.out.println(itr.next()); }` Which is equivalent to `for(Object obj: values) { System.out.println(obj); }` When you want to add elements while an iterator exist, you have to use a `ListIterator` and add elements through the iterator. – Holger Aug 23 '22 at 13:10

1 Answers1

5

This behaviour is documented in the ArrayList's documentation:

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException.

Adding an element counts as modifying the list "structurally", and note the wording "after the iterator is created".

The modification is detected when you start iterating over the list using next, which is where the exception is thrown.

See also Why is a ConcurrentModificationException thrown and how to debug it for details about what a ConcurrentModificationException is, though that question doesn't specifically address the case where you modify the collection immediately after creating the iterator, without calling next.

Sweeper
  • 213,210
  • 22
  • 193
  • 313