Java.util.ConcurrentModificationException when pasting into ArrayList

import java.util.ArrayList; import java.util.Iterator; import java.util.ListIterator; public class MyList { public static void main(String[] args) { ArrayList<String> al = new ArrayList<String>(); al.add("S1"); al.add("S2"); al.add("S3"); al.add("S4"); Iterator<String> lir = al.iterator(); while (lir.hasNext()) { System.out.println(lir.next()); } al.add(2, "inserted"); while (lir.hasNext()) { System.out.println(lir.next()); } } } 

The specific piece of code causes an error:

 Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(Unknown Source) at java.util.ArrayList$Itr.next(Unknown Source) at collections.MyList.main(MyList.java:32) 
+6
source share
3 answers

This is due to a change in the list of arrays after creating the Iterator .

The iterators returned by this iterator ArrayList and listIterator methods do not work quickly: if the list is structurally modified at any time after creating the iterator, in any way, except for the iterator itself deleting or adding methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of parallel modifications, the iterator fails quickly and cleanly, and not at the risk of arbitrary, non-deterministic behavior at an undetermined time in the future.

Documentation

 Iterator<String> lir = al.iterator(); // Iterator created while (lir.hasNext()) System.out.println(lir.next()); al.add(2, "inserted"); // List is modified here while (lir.hasNext()) System.out.println(lir.next());// Again it try to access list 

What you have to do here, create a new iterator object after modification.

 ... al.add(2, "inserted"); lir = al.iterator(); while (lir.hasNext()) System.out.println(lir.next()); 
+6
source

You modify the collection and then try to use the same iterator.

  • Get collection iterator again

     al.add(2, "inserted"); Iterator<String> lirNew = al.iterator(); while (lirNew.hasNext()) { System.out.println(lirNew.next()); } 
  • or use ListIterator

     ArrayList<String> al = new ArrayList<String>(); al.add("S1"); al.add("S2"); al.add("S3"); al.add("S4"); ListIterator<String> lir = al.listIterator(); while (lir.hasNext()) { System.out.println(lir.next()); } lir.add("insert"); while (lir.hasNext()) { System.out.println(lir.next()); } 
+3
source

You add an object to the list after starting the iterator. This will change the value of modCount in the inner class AbstractList $ Itr.class. next () of the iterator method will call the checkForComodification () method, which throws a ConcurrentModificationException. And this is called failure.

  //add in abstractList public void add(int index, E element) { if (index<0 || index>size) throw new IndexOutOfBoundsException(); checkForComodification(); l.add(index+offset, element); expectedModCount = l.modCount; size++; modCount++; //modCount changed } 

In AbstractList $ Itr

 int expectedModCount; public E next() { checkForComodification(); // cause ConcurrentModificationException try { E next = get(cursor); lastRet = cursor++; return next; } catch (IndexOutOfBoundsException e) { checkForComodification(); throw new NoSuchElementException(); } } private void checkForComodification() { if (l.modCount != expectedModCount) //modCount not equals to itr.expectedModCount throw new ConcurrentModificationException(); } 

repeat this code after adding:

 al.add(2, "inserted"); lir = al.iterator(); 
0
source

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


All Articles