Why a simultaneous modification of the foreach method, but not for the loop

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

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

I get a concurrentModificationException, but with a normal loop. I do not get any exceptions. in a regular 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 
}
+4
source share
1 answer

The ForEach loop will not loop directly on your collection. It uses the iterator of your collection. You can see the iterator in the implementation of your collections.

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 is equal

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

So, if you perform any operation here, and at the same time as changing the collection, the iterator under the hood gets confused and throws an exception.

From JLS

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

will be translated into:

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

Source: https://habr.com/ru/post/1682759/


All Articles