6

有类似的问题,但不完全是我想问的。我想问一下 Iterator 如何检查修改。

这个链接说它的实现存在于 AbstractList 类中,其中定义了一个 int 变量 modCount ,该变量提供列表大小已更改的次数。该值用于每个 next() 调用,以检查函数 checkForComodification() 中的任何修改。

但我无法真正理解它。如果仅在每次下一次调用后检查该值,那么如果我在同一个调用中执行删除然后添加,则大小不会改变并且 modCount 也不应该改变。但是在同一个循环迭代中删除和添加也会引发异常。

4

2 回答 2

8

如果您查看Collection实现的代码,请选择ArrayList; 我们在modCount中声明了一个变量AbstractList

protected transient int modCount = 0;

然后在每个修改方法(例如remove)中ArrayList我们有

public E remove(int index) {
    rangeCheck(index);

    modCount++;
    //....

所以modCount只会增加; 它永远不会递减。

然后Iterator我们有:

final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}

创建时拍摄expectedModCount的快照在哪里。modCountIterator

因此,如果在使用an 的同一个实例时对底层有任何修改,那么将抛出 a。ListIteratorConcurrentModificationException

我想有一个极端的情况,如果你进行了足够的修改,那么它int会溢出并再次返回到它的原始值——然而,这将是一个相当大的数字或修改;准确地说是2 32 。

于 2013-10-08T20:38:55.250 回答
6

modCount当列表被修改时总是增加(因此mod计数)所以当有删除时它也应该增加。因此,删除和添加调用都会增加。

正如蜘蛛鲍里斯所说,存在modCount溢出的角落案例,您可以通过以下方式看到它:

List<Integer> nums = new ArrayList<>();
for(int i = 0; i < 10; i++) nums.add(i);
for(int n : nums) {
    System.out.println(n);
    for(int i = -1; i < Integer.MAX_VALUE; i++) {
        nums.add(i);
        nums.remove(nums.size() - 1);
    }
}

它将(缓慢)打印 0 到 9 而不会引发任何异常。

于 2013-10-08T20:33:47.467 回答