繁体   English   中英

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

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

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

通常 java.util package 中的传统集合类使用一个 int 变量 (modCount) 来跟踪修改(添加和删除)。

当我们从这些集合类中请求 Iterator 时,返回的 Iterator 的 object 将提供现有的修改计数变量作为其预期的修改计数。

在调用 next() 方法时,迭代器 object 会根据预期的修改计数值检查当前修改计数变量值。

在不匹配的情况下,它会通过抛出 java.util package 中存在的 ConcurrentModificationException 快速失败,这是一个 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 s。 此外,请注意ConcurrentModificationException是由“轮询”引发的,而不是由“通知”引发的。 集合不需要跟踪其迭代器并在您调用集合上的方法时通知它们有关修改。 相反,当您在迭代器上调用方法时,每个迭代器都会检查集合是否已被修改。 如果您在修改集合后从不使用迭代器,它将永远不会有机会引发异常,因此,在您的示例中,不会引发异常,这是正确的行为。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM