java之List集合调用remove方法【陷阱及正确用法】

java之List集合调用remove方法【陷阱及正确用法】
《阿里巴巴开发手册》

一、通过forEach 调用List.remove() 

 java之List集合调用remove方法【陷阱及正确用法】

抛出异常信息: java.util.ConcurrentModificationException    ---》 fast_fail机制

java之List集合调用remove方法【陷阱及正确用法】 

查看remove方法源码,并没有和异常相关信息 

 java之List集合调用remove方法【陷阱及正确用法】

查看编译后的class文件 :

java之List集合调用remove方法【陷阱及正确用法】

原来for each的实际上使用的是iterator来遍历循环,其中核心方法是hasNext()和next()

看一下具体的实现: 

java之List集合调用remove方法【陷阱及正确用法】

java之List集合调用remove方法【陷阱及正确用法】

java之List集合调用remove方法【陷阱及正确用法】

这是java集合的 fast-fail机制,借助modCount参数,来记录修改次数,在迭代过程中判断modCount和expectedModCount是都相等,若不相等则会马上抛出 ConcurrentModificationException,在List.remove()中修改了modCount,导致modCount和expetedtModCount不相等,所以抛出异常

java之List集合调用remove方法【陷阱及正确用法】

二、正确用法

1,iterator.remove(),会对expectedModCount再次赋值

java之List集合调用remove方法【陷阱及正确用法】java之List集合调用remove方法【陷阱及正确用法】

2,下标正向循环 

java之List集合调用remove方法【陷阱及正确用法】

发现 ”有“没有删除成功,debug看看remove的过程吧

java之List集合调用remove方法【陷阱及正确用法】,删除之前,下标和List的数据保持正常

java之List集合调用remove方法【陷阱及正确用法】,这时0号下标的数据已经被删除了,删除之后,被删除元素后面的元素都会往前移动,i走到了1,那么”有“这个元素就被跳过了,所以需要手动修正下标的移动。

java之List集合调用remove方法【陷阱及正确用法】,此时就能正常删除了

3,通过下标倒序循环删除

java之List集合调用remove方法【陷阱及正确用法】