小编典典

Java中的迭代器如何知道何时引发ConcurrentModification异常

java

我有以下引发ConcurrentModificationException的代码,因为我在同一列表上使用了两个不同的迭代器,其中一个正在修改列表。因此,第二个迭代器在读取列表时会引发异常,因为其他某个迭代器已经修改了列表。

    List<Integer> list = new ArrayList<>();

    populate(list);//A method that adds integers to list

    ListIterator<Integer> iterator1 = list.listIterator();
    ListIterator<Integer> iterator2 = list.listIterator();

    while (iterator1.hasNext()) {
        if(iterator1.next() < 5)
            iterator1.remove();
    }

    while (iterator2.hasNext()){
        if(iterator2.next() < 5) {
         //Call handler   
        }
    }

我的问题是,如果尚未到达被删除的元素, 内部*
如何iterator2知道已被其他迭代器修改了?如何确定其他一些突变了?一种方法可能是跟踪大小,但这不是原因,因为其他迭代器可以替换任何元素。
*list``iterator1``iterator``list


阅读 211

收藏
2020-10-16

共1个答案

小编典典

回答此类问题的一种好方法是查看源代码,例如ArrayList的源代码。搜索ConcurrentModificationException

您应该能够说出事情的运作方式是这样的:

  • 集合对象具有修改计数,该修改计数从零开始,并在发生添加或删除或类似操作时增加。
  • 创建迭代器对象时,我们将集合的当前修改计数存储在迭代器中。
  • 每次使用迭代器时,它都会根据创建迭代器时获得的mod计数来检查集合的mod计数。如果这些值不同,则会引发异常。

根据您的情况,通过iterator1对列表执行删除操作会更改列表的结构操作计数(modCount)。当iterator2要求删除它时,它会看到其expectedModCount,最初接收为0,与列表的当前mod计数不同。

应当指出,这it.remove是一种特殊情况。当迭代器自行执行删除操作时,它会进行expectedModCount相应调整,以与基础列表保持同步。

2020-10-16