Java迭代器如何检测集合被修改抛出ConcurrentModificationException?

How Java iterators detect the collection is modified to throw ConcurrentModificationException?

迭代器如何Java检测集合被修改?尝试搜索,发现:

Usually the traditional collection classes in java.util package uses an int variable (modCount) to keep track of modifications (additions and deletions).

When we ask for an Iterator from these collection classes then a object of Iterator which is returned is provided with the existing modification count variable as its expected modification count.

Upon invoking the next() method the Iterator object checks the current modification count variable value against its expected modification count value.

In case of a mismatch it fails fast by throwing ConcurrentModificationException present in java.util package, its a RuntimeException.

但是如果我们

  1. 在修改之前推迟迭代器
  2. 修改合集
  3. 修改发生后创建第二个迭代器并迭代

第二个迭代器似乎一切正常,不是吗?那么 modCount 呢? 修改后的集合应该通知第一个迭代器抛出异常,同时不应该通知第二个。 请解释 modCount 是如何工作的?对 modCount 的行为进行编程或为每个迭代器保留 modCounts 的集合应该是一个挑战。 无论如何请澄清多个迭代器如何同时和独立地验证它们的一致性?

一般情况下是这样的:

class MyCollection implements Collection<E /* or whatever the elements are */> {
    private int modCount = 0;
    private class MyIterator implements Iterator<E> {
         private int expectedModCount;
         public MyIterator() {
              expectedModCount = modCount;
         }
         @Override
         public E next() {
             if(expectedModCount != modCount) throw new ConcurrentModificationException();
         }
         // etc.
    }
    @Override
    public Iterator<E> iterator() {
        return new MyIterator();
    }
    @Override
    public boolean add(E e) {
       modCount++;
       // etc.
    }
    // etc.
}

每个 MyIterator 知道 modCount 期望什么,将值记住为一个字段。您的迭代器 1 和 2 不会混淆,因为它们将是具有单独字段和单独值的单独对象,这意味着它们将期望不同的 modCount。此外,请注意 ConcurrentModificationException 是由 "polling" 抛出的,而不是由 "notification" 抛出的。当您在集合上调用方法时,集合不需要跟踪其迭代器并通知它们有关修改的信息。相反,每个迭代器都会在您调用迭代器上的方法时检查集合是否已被修改。如果您在修改集合后从不使用迭代器,它永远不会有机会抛出异常,因此,在您的示例中,不会抛出异常,这是正确的行为。