【问题标题】:Iterator inside Iterator ConcurrentModificationException迭代器内的迭代器 ConcurrentModificationException
【发布时间】:2017-11-11 05:10:28
【问题描述】:

我遇到以下问题:

给定一个 ArrayList(我们称之为列表),我怎样才能“双迭代”通过它而不得到 ConcurrentModificationException?

这是我尝试过的:

iterator out = list.iterator();
iterator in;
while(out.hasNext()){
    ...
    in = list.iterator();
    while(in.hasNext()){
        ...
        if(something)
             in.remove();
    }

【问题讨论】:

  • 这是什么????
  • 它在里面,抱歉我打字太匆忙了
  • 您不能使用同一个列表的两个迭代器并使用一个迭代器删除一个元素,而另一个迭代器仍在忙于迭代该集合。
  • 你为什么要这样做?您能否解释一下您打算通过这种双重迭代方法实现什么目标?

标签: java iterator concurrentmodification


【解决方案1】:

通过调用List#iterator 方法提供的Iterator 实例保留了一个count 标量,允许检测Collection 容器的外部更改。

当通过相同的Iterator#remove(T) 调用以外的任何其他方式从集合中删除元素时,count 不会在后台更新。 因此,当您通过迭代器实例请求 #next() 元素时,会根据 预期值 检查 count 并且如果两个值不匹配(因为元素已经通过另一个迭代器删除)ConcurrentModificationException 被抛出(即使您可能在单线程环境中工作)。

正如@Michael 所说,解决方案应该是跟踪应该删除的容器元素,然后执行批量删除:

Collection<Object> temp = new ArrayList<>();
iterator out = list.iterator();
iterator in;
while (out.hasNext()) {
    // ...
    in = list.iterator();
    while (in.hasNext()) {
        // ...
        if(something)
             // just mark the element for deletion
             temp.add(in.next());
    }
}

// delete all the obsolete elements
list.removeAll(temp);

【讨论】:

    【解决方案2】:

    您正在尝试修改迭代器。它会给你 concurrentModification 异常。

    在 java 8 中,您可以使用以下方法轻松删除它 list.removeIf(someCondition)

    试试这个链接java8 collections

    【讨论】:

      【解决方案3】:

      你不能那样做。一个潜在的解决方案可能是标记要删除的对象,例如:

      final List<Foo> toRemove = new ArrayList<>();
      
      for (Foo a : list)
      {
          for (Foo b : list)
          {
              if (something)
              {
                  toRemove.add(b);
              }
          }
      }
      list.removeAll(toRemove);
      

      您可能需要进行一些额外的检查才能确定该对象尚未标记为移除。鉴于你的例子含糊不清,这很难说。

      【讨论】:

        【解决方案4】:

        在一次迭代器创建者的集合中如果您尝试不通过相同的迭代器修改内容,它将引发并发异常。如果您需要某种特殊类型的迭代器,那么您可以继续实现自己的。

        【讨论】:

        • 在这种情况下,它会在线程“main” java.lang.IllegalStateException 中抛出异常,而不是并发修改异常。我正在寻找它背后的原因。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-09-26
        • 2017-10-18
        • 2015-12-23
        • 1970-01-01
        • 1970-01-01
        • 2014-05-23
        • 1970-01-01
        相关资源
        最近更新 更多