执行ArrayList的remove(object)方法抛异常?
简介
或许有很多小伙伴都尝试过如下的代码:
ArrayList<Object> list = ...;for (Object object : list) {
if (条件成立) {
list.remove(object);
}
}
然后会发现抛出java.util.ConcurrentModificationException
异常,这是一个并发异常。那么这个到底是什么情况?首先需要介绍一下增强for循环
增强for循环
增强for循环是Java1.5后,Collection实现了Iterator接口后出现的。增强for循环的代码如下
for (Object object : list) {// 操作
}
其实增强for循环就是使用Iterator迭代器进行迭代的,增强for循环就变成下面这样:
Iterator<Object> iterator = list.iterator();while (iterator.hasNext()) {
iterator.next();
// 操作
}
那么为什么在增强for循环中调用list.remove(object)
会出事呢?那么咱们看看ArrayList下的 Iterator的实现类: Itr类
Itr子类
Itr子类是Iterator的实现类,属于ArrayList私有的局部内部类。我截取了Itr类的部分代码,如下:
privateclassItrimplementsIterator<E> {int cursor; // index of next element to return
int expectedModCount = modCount;
Itr() {}
publicbooleanhasNext(){
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next(){
checkForComodification();
...
}
finalvoidcheckForComodification(){
if (modCount != expectedModCount)
thrownew ConcurrentModificationException();
}
}
elementData 是ArrayList存放元素的数组,上面代码没有贴出来。
size 是elementData实际存放的容量大小
modCount 记录elementData容量的修改次数
expectedModCount 记录实例化迭代器Itr时,elementData容量的修改次数
注意!:在迭代器中,当执行next
方法的时候,会去调用checkForComodification
方法,判断elementData 的容量是否被修改过。
然后来看看ArrayList的remove(object)方法,截取部分代码如下:
publicbooleanremove(Object o){for (int index = 0; index < size; index++)
if (找到目标元素) {
fastRemove(index);
returntrue;
}
returnfalse;
}
privatevoidfastRemove(int index){
modCount++;
// 移除操作
}
可以发现,调用remove(object)方法时调用了fastRemove方法,在fastRemove方法中执行modCount++
!
现在把文章开头的代码拷下来,再来分析一次:
ArrayList<Object> list = ...;for (Object object : list) {
if (条件成立) {
list.remove(object);
}
}
当执行了list.remove
时,执行modCount++
。此时迭代器再往下进行迭代,执行了next方法,发现 modCount != expectedModCount
,那么则抛出java.util.ConcurrentModificationException
异常。 之所以Iterator认为是一个并发异常。是因为你不在迭代器里操作,而是在迭代器外面进行remove操作呀!
难道没有其他解决方案吗?有滴。
解决方案
那么就是使用Itr的 remove方法。Itr子类重写了 remove 方法,这里部分代码:
publicvoidremove(){...
try {
ArrayList.this.remove(需要删除元素的索引);
...
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
thrownew ConcurrentModificationException();
}
}
其实很简单,就是remove后,把 expectedModCount 同步一下 modCount 的值,这就解决了。完整代码如下:
ArrayList<Object> list = ...;Iterator<Object> iterator = list.iterator();
while (iterator.hasNext()) {
iterator.next();
iterator.remove();
}
总结
本来我还不知道增强for循环是调用Iterator进行迭代的,要不是我debug了一波,我还不知道呐。还是小有收货。
个人博客网址: colablog.cn/
如果我的文章帮助到您,可以关注我的微信公众号,第一时间分享文章给您
以上是 执行ArrayList的remove(object)方法抛异常? 的全部内容, 来源链接: utcz.com/a/31325.html