本网站(662p.com)打包出售,且带程序代码数据,662p.com域名,程序内核采用TP框架开发,需要联系扣扣:2360248666 /wx:lianweikj
精品域名一口价出售:1y1m.com(350元) ,6b7b.com(400元) , 5k5j.com(380元) , yayj.com(1800元), jiongzhun.com(1000元) , niuzen.com(2800元) , zennei.com(5000元)
需要联系扣扣:2360248666 /wx:lianweikj
执行ArrayList的remove(object)方法抛异常?
iamitnan · 299浏览 · 发布于2020-07-10 +关注

简介#

或许有很多小伙伴都尝试过如下的代码:

ArrayList 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 iterator = list.iterator();while (iterator.hasNext()) {
    iterator.next();    // 操作}

那么为什么在增强for循环中调用list.remove(object)会出事呢?那么咱们看看ArrayList下的 Iterator的实现类: Itr类

Itr子类#

Itr子类是Iterator的实现类,属于ArrayList私有的局部内部类。我截取了Itr类的部分代码,如下:

private class Itr implements Iterator {    int cursor;       // index of next element to return
    int expectedModCount = modCount;

    Itr() {}    public boolean hasNext() {        return cursor != size;
    }    @SuppressWarnings("unchecked")    public E next() {
        checkForComodification();
        ...
    }    
    final void checkForComodification() {        if (modCount != expectedModCount)            throw new ConcurrentModificationException();
    }
}

elementData 是ArrayList存放元素的数组,上面代码没有贴出来。
size 是elementData实际存放的容量大小
modCount 记录elementData容量的修改次数
expectedModCount 记录实例化迭代器Itr时,elementData容量的修改次数
注意!:在迭代器中,当执行next方法的时候,会去调用checkForComodification方法,判断elementData 的容量是否被修改过。


然后来看看ArrayList的remove(object)方法,截取部分代码如下:

public boolean remove(Object o) {    for (int index = 0; index < size; index++)	    if (找到目标元素) {
	        fastRemove(index);	        return true;
	    }	return false;
}private void fastRemove(int index) {
    modCount++;    // 移除操作}

可以发现,调用remove(object)方法时调用了fastRemove方法,在fastRemove方法中执行modCount++!
现在把文章开头的代码拷下来,再来分析一次:

ArrayList list = ...;for (Object object : list) {    if (条件成立) {
        list.remove(object);
    }
}

当执行了list.remove时,执行modCount++。此时迭代器再往下进行迭代,执行了next方法,发现 modCount != expectedModCount,那么则抛出java.util.ConcurrentModificationException异常。 之所以Iterator认为是一个并发异常。是因为你不在迭代器里操作,而是在迭代器外面进行remove操作呀!
难道没有其他解决方案吗?有滴。

解决方案#

那么就是使用Itr的 remove方法。Itr子类重写了 remove 方法,这里部分代码:

public void remove() {
    ...    try {
        ArrayList.this.remove(需要删除元素的索引);
        ...
        expectedModCount = modCount;
    } catch (IndexOutOfBoundsException ex) {        throw new ConcurrentModificationException();
    }
}

其实很简单,就是remove后,把 expectedModCount 同步一下 modCount 的值,这就解决了。完整代码如下:

ArrayList list = ...;
Iterator iterator = list.iterator();while (iterator.hasNext()) {
    iterator.next();
    iterator.remove();
}

总结#

本来我还不知道增强for循环是调用Iterator进行迭代的,要不是我debug了一波,我还不知道呐。还是小有收货。

 

相关推荐

PHP实现部分字符隐藏

沙雕mars · 1325浏览 · 2019-04-28 09:47:56
Java中ArrayList和LinkedList区别

kenrry1992 · 908浏览 · 2019-05-08 21:14:54
Tomcat 下载及安装配置

manongba · 970浏览 · 2019-05-13 21:03:56
JAVA变量介绍

manongba · 962浏览 · 2019-05-13 21:05:52
什么是SpringBoot

iamitnan · 1086浏览 · 2019-05-14 22:20:36
加载中

0评论

评论
分类专栏
小鸟云服务器
扫码进入手机网页