并发修改异常并不总是被抛出

5

在这个示例中,使用list.remove((Object)93)会导致ConcurrentModificationException异常:

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(14);
list.add(2);
list.add(44);
list.add(41);
list.add(93);
list.add(20);

for(Iterator<Integer> it = list.iterator();it.hasNext();) {
    list.remove((Object)93);
    it.next();
}
System.out.println(list);

然而,当我将list.remove((Object)93)放入if语句中时,它不会引起任何错误。为什么?
for(Iterator<Integer> it = list.iterator();it.hasNext();) {
    int num = it.next();
    if(num == 93) {
        list.remove((Object)93);
    }
}
System.out.println(list);

1
我不相信这是重复的,至少和链接的问题不同。这个问题明确地讨论了在迭代列表时使用list.remove()删除一个项目,而不是使用it.remove() - Michael Berry
1个回答

5
在第一个示例中,您在迭代器迭代时修改了列表,因此在第一次迭代时会出现ConcurrentModificationException异常,这是预期的。
在第二个示例中,从ArrayList中删除93后,it.next()甚至不会被调用,因为hasNext将返回false-请参见ArrayList.Itr::hasNext的实现。
public boolean hasNext() {
    return this.cursor != ArrayList.this.size;
}

它只检查ArrayList的大小是否与光标不同。在您的示例中,93元素位于倒数第二个位置。删除93元素后,大小将减小一,因此it.next()将评估为false,并且it.next将不被调用,不会抛出任何异常。

这是一个巧合,您将93放在倒数第二个位置,因此没有收到异常。尝试在93之后向ArrayList添加另一个值,就会像第一个示例中那样抛出ConcurrentModificationException异常。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接