Search code examples
javaconcurrentmodification

why concurrent modification on foreach method but not on for loop


 ArrayList<Integer> targets = new ArrayList<Integer>();
 targets.add(2);
 targets.add(2);

 for (Integer testInt : targets )
 {
       targets.add(1);
 }

I am getting an concurrentModificationException,But with normal for loop. I am not getting any exception. in normal forloop like:-

for(int i=0;i<target.size();i++)
{
   System.out.println(target.get(i));
   target.add(22); //no exception
   target.remove(2) // no exception 
}

Solution

  • ForEach loop won't loop directly on your collection. It uses the iterator of your collection behind. you can see the iterator in your collections implementation.

    From Arraylist source code

    735 
    736     public Iterator<E> More ...iterator() {
    737         return new Itr();
    738     }
    
    
    An optimized version of AbstractList.Itr
    742 
    743     private class More ...Itr implements Iterator<E> {
    744         int cursor;       // index of next element to return
    

    And your foreach loop equals to

    for(Iterator<Integer> i = targets.iterator(); i.hasNext(); ) {
      Integer element = i.next();
      //To do
    }
    

    So if you doing any operation here, and the same time you modifying the collection, iterator under the hood got confuse and throws exception.

    From JLS

    List<? extends Integer> l = ...
    for (float i : l) ...
    

    will be translated to:

    for (Iterator<Integer> #i = l.iterator(); #i.hasNext(); ) {
        float #i0 = (Integer)#i.next();
        ...