当我运行以下代码时,我的程序抛出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++;
}
}
答案 0 :(得分:5)
不要在dateWiseValues
上使用基于范围的 for 循环,而是明确使用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
的子类型。实现List
的两种常见具体类型是ArrayList
和LinkedList
。每个类的散文级别文档包含以下警告:
此类的
iterator
和listIterator
方法返回的迭代器是快速失败的:如果在创建迭代器之后的任何时候对列表进行结构修改,除了通过{{1自己的Iterator
或remove
方法,迭代器将抛出add
。因此,面对并发修改,迭代器会快速而干净地失败,而不是在未来不确定的时间冒着任意的,非确定性行为的风险。
请注意,它警告您必须在迭代期间使用ConcurrentModificationException
进行变异,否则下次使用相同或任何其他迭代器遍历同一基础列表时,您将面临抛出Iterator#remove()
。
答案 1 :(得分:2)
当您使用增强的for
循环时,它会在幕后隐式使用Iterator
。这是Iterator
抛出ConcurrentModificationException
,而不是您在外部iterator
循环中定义的显式迭代器for
。除非您调用Iterator#remove()
,这会删除当前列表项并避开Iterator
,否则您无法在ConcurrentModificationException
迭代时从列表中删除。
您有两个选择:
for
循环以明确使用while
循环和Iterator
,然后
如果要删除项目,请致电remove()
。List
项。当你确定你想要的时候
删除该项目,add
将其移至要删除的项目列表。然后,
在完成迭代后,请在原始列表中调用removeAll
以删除您要删除的所有项目。