插入 ArrayList 时出现 java.util.ConcurrentModificationException
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18227245/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
java.util.ConcurrentModificationException while inserting in ArrayList
提问by user2681668
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 particular piece of code throws 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)
回答by Aniket Thakur
You are modifying the Collection and then trying to use the same iterator.
您正在修改集合,然后尝试使用相同的迭代器。
Get the 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()); }
再次获取 Collection 迭代器
al.add(2, "inserted"); Iterator<String> lirNew = al.iterator(); while (lirNew.hasNext()) { System.out.println(lirNew.next()); }
或使用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()); }
回答by Subhrajyoti Majumder
It happens due to array list is modified after creation of Iterator
.
这是由于创建Iterator
.
The iterators returned by this ArrayList'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. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.
此 ArrayList 的 iterator 和 listIterator 方法返回的迭代器是快速失败的:如果在创建迭代器后的任何时间对列表进行结构修改,除了通过迭代器自己的 remove 或 add 方法之外,迭代器将抛出 ConcurrentModificationException。因此,面对并发修改,迭代器快速而干净地失败,而不是冒着在未来不确定的时间出现任意、非确定性行为的风险。
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 should do here create new iterator object after modification.
你应该在这里做的是在修改后创建新的迭代器对象。
...
al.add(2, "inserted");
lir = al.iterator();
while (lir.hasNext())
System.out.println(lir.next());
回答by criszhao
You add object to list, after the iterator is instanced. This will change the value of modCount in inner class AbstractList$Itr.class. next() method of iterator will call checkForComodification() method, which throws a ConcurrentModificationException. And this is so called fail-fast.
在实例化迭代器后,将对象添加到列表中。这将改变内部类 AbstractList$Itr.class 中 modCount 的值。迭代器的 next() 方法将调用 checkForComodification() 方法,该方法抛出 ConcurrentModificationException。这就是所谓的快速失败。
//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
在 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();
}
redo this code after your add:
添加后重做此代码:
al.add(2, "inserted");
lir = al.iterator();