为什么从列表中删除元素会抛出ConcurrentModificationException?

use*_*488 2 java iterator exception

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++;
    }
} 
Run Code Online (Sandbox Code Playgroud)

seh*_*seh 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();
}
Run Code Online (Sandbox Code Playgroud)

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


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

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

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