迭代器使用过程中为什么抛出ConcurrentModificationException

Posted 128-cdy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了迭代器使用过程中为什么抛出ConcurrentModificationException相关的知识,希望对你有一定的参考价值。

      出现的场景:在迭代器对集合进行遍历的同时,集合本身进行变更操作(add(), remove(), set())。

当正常调用时:

import java.util.ArrayList;
import java.util.Iterator;

public class TestDemo {
    public static void main(String[] args) {
        ArrayList<Integer> a = new ArrayList<>();
        a.add(1);
        a.add(3);
        a.add(5);
        a.add(6);
        Iterator<Integer> iterator = a.iterator();
        while (iterator.hasNext()){
            System.out.print(iterator.next()+" ");
        }
    }
}

结果:

技术图片

 

 当调用interator()接口里面的remove()操作时:

技术图片

 

 

 

 结果:

 技术图片

 

 当调用ArrayList的对象下的remove()或者add();

技术图片

 

或者

 技术图片

 

 

   便会报错:

 技术图片

 

 那么为何会出现这种情况呢?

        首先我们应该知道,ArrayList底层的modCount这个属性,这也是个版本记录号每对ArrayList进行一次增删改操作,都会进行modCount++操作。并且在迭代器的使用中,会将当前的modCount的值赋给expectedModCount迭代器的这个属性。

我们先来看看得ArrayList内地迭代器的部分源码:

技术图片

 

 

可以看到每次Iterator的对象调用next()操作时,都会调用checkForComodification()的方法,具体我们来看看这个方法。

技术图片

再来看看迭代器中的remove()方法:

技术图片

 

     可以看到迭代器中的remove()方法虽然也是用的ArrayList的remove()方法,正如前面所说,那也会对modCount的值进行改变,但是关键就在于expectedModCount = modCount,它会将改变的值重新赋给expectedModCount。然后每次用完迭代器中的remove()方法后,就算再次用nex()的方法,调用checkForComodification()方法,就不会抛出异常。但是如果直接用ArrayList的对象调用增删改的方法,modCount值得改变,不会引起expectedModCount值的变化,再次调用迭代器,调用到checkForComodification()方法时,便会抛出ConcurrentModificationException的错误。

     总的来说,在调用迭代器的时候,就用迭代器的remove()方法,否则就会出现错误,还有迭代器的一个对象只能进行一次迭代,要多次迭代,,便要创建多个对象。

以上是关于迭代器使用过程中为什么抛出ConcurrentModificationException的主要内容,如果未能解决你的问题,请参考以下文章

为什么迭代器只能被一个集合使用呢 为什么迭代器不能在迭代过程中 ?增删呢 是因为 每次迭代时候 把之前的元素给拿出去了 如果你在操作过程中将下一个迭代元素给拿走了(迭代器不具备自动判断长度功能 她依旧

迭代器

redux-saga 的单元测试抛出错误:必须在迭代器上调用 runSaga

Java 小程序在从迭代器数组中删除对象时抛出错误

HashMap 线程不安全相关问题

迭代器生成器面向过程编程