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

标签 java iterator concurrentmodification

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 的行为进行编程或为每个迭代器保留 modCount 的集合应该是一个挑战。 无论如何,请澄清多个迭代器如何同时且独立地验证其一致性?

最佳答案

一般来说,它的工作原理是这样的:

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 是通过“轮询”而不是“通知”引发的。当您调用集合上的方法时,集合不需要跟踪其迭代器并通知它们有关修改的信息。相反,当您在迭代器上调用方法时,每个迭代器都会检查集合是否已被修改。如果在修改集合后从不使用迭代器,它将永远不会有机会抛出异常,因此,在您的示例中,不会抛出异常,这是正确的行为。

关于java - Java迭代器如何检测集合被修改而抛出ConcurrentModificationException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58756042/

相关文章:

java - 为什么 RecyclerView onBindViewHolder 只调用一次?

java - 使用递归选择数组的奇数/偶数元素

python - 分离 __iter__ 和 __next__ 方法

c++ - 在 vector 结构中显示 vector 结构

c++ - 如何确保迭代器模板参数与模板类的模板参数具有相同的数据类型

java - Guava MultiMap 和 ConcurrentModificationException

java - 如何修剪字符串中的特定字符

java - 将java对象转换为相应类型的xml

java - map 并发修改问题

java - CopyOnWriteArrayList/ConcurrentHashMap内部如何处理Concurrent修改异常?