什么时候会抛出并发修改异常,iterator remove 方法如何工作?

When will be concurrent modification exception will be thrown and how iterator remove method will work?

根据 javadocs,当我们尝试在迭代时对集合进行结构性修改时,将抛出并发修改异常。it.Only迭代器删除方法不会抛出并发修改异常。

我分析过以下几种不会抛出并发修改异常的情况:

List<Integer> var=new ArrayList<Integer>();
var.add(3);
var.add(2);
var.add(5);

第一种情况:

for(int i = 0; i<var.size(); i++){
    System.out.println(var.get(i));
    var.remove(i);
}

第二个案例:

for(Integer i:var){
    System.out.println(i);
    if(i==2){
        var.remove("5");
    }
}

1) 谁能解释一下这些情况是如何不抛出 Conncurrent Modification Exception 的? 2) 谁能告诉我 iterator.remove 内部是如何工作的?

第一个实现没有使用迭代器,所以当然不会抛出。只有 Iterators 抛出(尽管索引的 for 循环也会被破坏,例如,如果你删除一个元素,然后所有其他元素的索引从你的迭代中移出)。 Java就是没法告诉你。

第二种实现没有改变内容。 var.remove("5") 尝试删除不存在的 字符串 "5"(列表仅包含整数),因此不会发生任何更改。此外,当 i 是盒装大写字母时 i == 2 是危险的 - I Integer;考虑改为 for (int i : var)

最后,没有实现保证会抛出 ConcurrentModificationException;它只是试图这样做来警告您迭代器已损坏。无论是否抛出异常,迭代器 被迭代过程中执行的修改破坏,Java 只是想警告你。

根据Javadoc of ArrayList

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException.

因此,抛出 CME 的条件是:

  • 必须有迭代器(或列表迭代器)
  • 您必须对列表进行结构修改,而不是通过迭代器(即添加或删除元素)

而且,也许不那么明显:

  • 结构修改后,必须调用结构修改前创建的迭代器上的方法。

即在您对其调用 next()remove() 之前,迭代器不会尝试检测 CME。