2

ConcurrentModificationException当我运行以下代码时,我的程序会抛出异常。通过一些研究,我发现在迭代器循环中无法添加或删除列表中的元素。我现在该怎么做才能删除List<Bean>?

for (Iterator<Entry<String, List<Bean>>> iterator = dataMap.entrySet().iterator(); iterator.hasNext();) {
    Entry<String, List<Bean>> entry = (Entry<String, List<Bean>>)iterator.next();
    List<Bean> dateWiseValues = (List<Bean>) entry.getValue();
    int j = 0;
    for (Bean statBean : dateWiseValues) {
        for (int i = 0; i < commonElements.size(); i++) {
            if(statBean.getDate().equalsIgnoreCase(commonElements.get(i))) {
                //remove the bean
                entry.getValue().remove(j);
            }
        }
        j++;
    }
} 
4

2 回答 2

5

与其使用基于范围的for循环dateWiseValues,不如使用Iterator显式的,以便您可以调用Iterator#remove()

for (final Iterator<? extends Bean> it = dateWiseValues.iterator();
     it.hasNext();) {
  final Bean statBean = it.next();
  for (int i = 0, last = commonElements.size(); i != last; ++i)
    if (statBean.getDate().equalsIgnoreCase(commonElements.get(i)))                
      it.remove();
}

通常,只要您通过集合的迭代器之一进行迭代,就可以安全地从集合和底层集合中删除元素。


虽然我们看不到 的具体类型dateWiseValues,但我们知道它是 的子类型List。两种常见的具体实现类型ListArrayListLinkedList。这些类中的每一个的散文类级别文档都包含以下警告:

此类的iteratorlistIterator方法返回的迭代器是快速失败的:如果在创建迭代器后的任何时候列表在结构上被修改,除了通过Iterator自己的removeadd方法之外的任何方式,迭代器将抛出一个ConcurrentModificationException. 因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒任意的、非确定性的行为。

请注意,它警告您必须在迭代期间使用突变,否则下次使用相同或任何其他迭代器遍历相同的基础列表时,Iterator#remove()您将面临抛出异常。ConcurrentModificationException

于 2013-04-20T00:02:32.020 回答
2

当您使用增强循环时,它会在幕后for隐式使用。Iterator这是Iterator抛出的,而不是您在外循环中定义ConcurrentModificationException的显式迭代器。在 an 迭代列表时,您不能从列表中删除,除非您调用,这将删除当前列表项并避免.iteratorforIteratorIterator#remove()ConcurrentModificationException

你的两个选择:

  • 重写增强for循环以显式使用while循环和Iterator,然后remove()在要删除项目时调用。
  • 创建一个List要删除的项目。当您确定要删除该项目时,add将其添加到要删除的项目列表中。然后, 您完成迭代后,调用removeAll原始列表以删除您希望删除的所有项目。
于 2013-04-20T00:02:33.317 回答