Java 中的迭代器如何知道何时抛出 ConcurrentModification 异常
How does an Iterator in Java know when to throw ConcurrentModification Exception
我有以下抛出 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
?一种方法是跟踪大小,但这不是原因,因为其他一些迭代器可以替换任何元素。
回答此类问题的一个好方法是查看源代码,例如 the source code for ArrayList。搜索 ConcurrentModificationException
.
你应该能够看出事情是这样运作的:
- 集合对象有一个 mod化计数,从零开始,每当发生添加或删除或类似操作时都会增加。
- 创建迭代器对象时,我们将集合的当前mod化计数存储在迭代器中。
- 每次使用迭代器时,它都会检查集合的 mod 计数与迭代器在创建时获得的 mod 计数。如果这些值不同,则抛出异常。
在您的情况下,删除 iterator1
对列表执行的操作会更改列表的结构操作计数 (modCount
)。当 iterator2
被要求删除时,它看到它的 expectedModCount
,它最初收到的是 0,与列表的当前 mod 计数不同。
需要注意的是it.remove
是一个特例。当迭代器删除自身时,它的 expectedModCount
会相应地进行调整,以与底层列表保持同步。
我有以下抛出 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
?一种方法是跟踪大小,但这不是原因,因为其他一些迭代器可以替换任何元素。
回答此类问题的一个好方法是查看源代码,例如 the source code for ArrayList。搜索 ConcurrentModificationException
.
你应该能够看出事情是这样运作的:
- 集合对象有一个 mod化计数,从零开始,每当发生添加或删除或类似操作时都会增加。
- 创建迭代器对象时,我们将集合的当前mod化计数存储在迭代器中。
- 每次使用迭代器时,它都会检查集合的 mod 计数与迭代器在创建时获得的 mod 计数。如果这些值不同,则抛出异常。
在您的情况下,删除 iterator1
对列表执行的操作会更改列表的结构操作计数 (modCount
)。当 iterator2
被要求删除时,它看到它的 expectedModCount
,它最初收到的是 0,与列表的当前 mod 计数不同。
需要注意的是it.remove
是一个特例。当迭代器删除自身时,它的 expectedModCount
会相应地进行调整,以与底层列表保持同步。