问题描述
用增强for循环遍历List中的元素时,如果循环体中做了删除操作报出如下异常:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
at test.main(test.java:13)
复现问题
public class test {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 5; i++){
list.add(i);
}
for (Integer i : list){
if (i == 4){
list.remove(i);
System.out.println("remove");
}
}
}
}
看看问题是怎么产生的
=.=反编译我是不会啦,贴个别人的
https://blog.csdn.net/puppet121/article/details/81546260
也就是增强for循环到了虚拟机会变成Iterator执行
for(java.util.Iterator i$ = list.iterator(); i$.hasNext();)
{
String s = (String) i$.next();
{
list.remove(s);
}
}
先了解modCount:记录对“影响了List size”的操作 次数
- modCount
The number of times this list has been structurally modified.
Structural modifications are those that change the size of the list, or otherwise perturb it in such a fashion that iterations in progress may yield incorrect results.
然后看抛异常的地方:
private class Itr implements Iterator<E> {
/**
* 这是ArrayList的内部类,Itr在我们执行遍历操作的时候被初始化,expectedModCount = 我们执行的5次插入操作
*/
int expectedModCount = modCount;
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
}
然而执行list.remove(Object obj)后,调用的是ArrayList自己的remove方法,虽然modCount+1,但是用于遍历List的itr对象中的expectedModCount依然=5,这样就在遍历下一个元素是就被检查出不一致抛异常啦~
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
正确的处理姿势
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 5; i++){
list.add(i);
}
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()){
int i = iterator.next();
if (i == 1){
//要领就是:既然外面用的iterator遍历,那里面也要用iterator删除,这样就保证两个操作数的一致性啦
iterator.remove();
}
}
--------我是分界线------------
mentor看代码刚问完会不会有问题 瞬间就抛了异常。。。