何时会抛出并发修改异常以及迭代器删除方法如何工作?

时间:2016-02-02 18:50:48

标签: java arraylist collections concurrentmodification

根据javadocs,当我们尝试在迭代时对结构进行结构修改时,会抛出并发修改异常。只有迭代器remove方法才会抛出并发修改异常。

我已经分析了以下不会抛出并发修改异常的情况:

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内部是如何工作的?

2 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:0)

根据Javadoc of ArrayList

  

此类的迭代器和listIterator方法返回的迭代器是快速失败的:如果在创建迭代器之后的任何时候对列表进行结构修改,除了通过迭代器自己的remove或add方法之外,迭代器将抛出一个ConcurrentModificationException。

因此,CME将被抛出的条件是:

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

而且,也许不那么明显:

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

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