foreach循环remove倒数第二个不会报ConcurrentModificationException异常

问题原因remove倒数第二个后,ArrayList集合私有属性size=size -1。
接着迭代下一次循环时先判断 hasNext,
 public boolean hasNext() {
     return cursor != size;
}
此时游标cursor == size 
hasNext返回false 循环结束。会丢失最后一个元素的遍历。


问题的关键点是用的是集合的remove方法,而不是用的是迭代器的remove方法。

正如:用的不是同一厂商的东西,无法保证整体质量效果。

1.迭代器的remove方法

在集合迭代的过程中,为了判断线程的安全,迭代器的方法都会判断集合实际修改的次数与预期的修改次数。
迭代器的remove方法删除元素时会立即修改集合实际修改的次数与预期的修改次数。如下图 红框

附:remove 元素请使用 Iterator方式,如果并发操作,需要对 Iterator 对象加锁。

2.ArrayList的remove方法

增加List的修改次数。

使用ArrayList的remove方法后,集合还未遍历完,继续下次迭代,调用迭代器的next方法取下一个集合元素。

3.迭代器next方法:

next 中checkForComodification会判断预期元素修改的次数是否等于集合的实际的元素修改次数,由于使用的ArrayList的remove方法。造成modCount != expectedModCoun抛出ConcurrentModificationException异常
 

写在最后:阿里巴巴java开发手册的一个强制规范:

不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator方式,如果并发操作,需要对 Iterator 对象加锁。

猜你喜欢

转载自blog.csdn.net/xiangzheniunai/article/details/83183247