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



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

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

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)谁能解释一下这些情况如何不抛出并发修改异常?2)任何人都可以告诉iterator.move内部是如何工作的吗?

根据 ArrayList 的 Javadoc :

此类的迭代

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

因此,抛出CME的条件是:

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

而且,也许不是那么明显:

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

即迭代器不会尝试检测 CME,直到您调用 next() 或在其上remove()

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

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

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

最新更新