有类似的问题,但不完全是我想问的问题。 我想问一下Iterator如何检查修改。
This link表示它的实现存在于AbstractList类中,其中定义了一个int变量modCount,它提供了列表大小已更改的次数。在每次next()调用中使用此值来检查函数checkForComodification()中的任何修改。
但我真的不明白。如果仅在每次下一次调用后检查该值,那么如果我执行删除,然后添加相同的调用,则大小不会更改,并且modCount也不应更改。但删除和添加相同的循环迭代也会抛出异常。
答案 0 :(得分: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
是modCount
创建Iterator
时的快照。
因此,如果在List
的同一个实例正在使用时,对基础Iterator
进行任何修改,则会抛出ConcurrentModificationException
。< / p>
我认为有一个极端情况,如果你进行了足够的修改,那么int
会溢出并再次返回原始值 - 这将是一个相当大的数字或修改然而;确切地说,2 32 。
答案 1 :(得分: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而不会抛出任何异常。