maoruibin.github.com
maoruibin.github.com copied to clipboard
为什么使用 Iterator 可以在遍历时删除元素而不报错
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("9");
list.add("3");
list.add("4");
list.add("5");
list.add("6");
// 正常 for 循环迭代删除 9 这个元素 报错
for(String item:list){
if("9".equals(item)){
list.remove(item);
}
}
//使用迭代器删除 9 正常
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
if ("9".equals(iterator.next())) {
iterator.remove();
}
}
使用正常的 for 循环遍历 list 报错如下所示

具体报错的代码在 list 中如下所示:
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
这里因为修改次数跟期望修改次数不一致所以奔溃了。
其中 modCount 是指 list 被修改的次数,这个数字会在 list 执行 add、remove 等操作时都会改变,而 expectedModCount 默认不会改变, list 在执行遍历时会调用 checkForComodification 方法进行检查,此时如果发现两个数值不一样就会 crash。
如何避免这个错误呢,其实想想也比较简单,就是在执行 add 或者 remove 时让 expectedModCount 跟 modeCount 保持一致即可,但是 list 的这两个方法中只会修改 modCount,不会修改 expectedModCount,所以不行。
现在回到文章的标题,为什么使用 iterator 就可以,因为 iterator 的 remove 方法在执行时,不仅调用了 list 的 remove ,还修改了 expectedModCount。

如上所示,所以用 iterator 执行迭代时可以执行删除操作,而不会报异常。