本文主要介绍,java中list集合移除元素的那些坑,今天小编就和大家一起来了解一下吧!
一、问题案例
1.1、for循环移除
1 | |
输出结果:
1 | |
有没有发现有蹊跷的地方?
从输出结果可以看的出,移除后的元素,并没有把内容为11的都移除掉!
发生了什么?
删除了第一个11后,集合里的元素个数减1,后面的元素往前移了1位,此时,第二个11已经移到了索引index=1的位置,而此时i马上i++了,list.get(i)获得的是数据12。同时list.size()的值也在减小。所以最后输出那个结果。
1.2、fore循环移除
1 | |
输出结果:

抛ConcurrentModificationException异常!
foreach 写法实际上是对的 Iterable、hasNext、next方法的简写。因此我们从List.iterator()着手分析,跟踪iterator()方法,该方法返回了 Itr 迭代器对象。
找到List的迭代器类
1 | |
Itr对象
1 | |
通过代码我们发现 Itr 是 ArrayList 中定义的一个私有内部类,在 next、remove方法中都会调用 checkForComodification 方法,该方法的作用是判断 modCount != expectedModCount是否相等,如果不相等则抛出ConcurrentModificationException异常。每次正常执行 remove 方法后,都会对执行expectedModCount = modCount赋值,保证两个值相等!
那么问题基本上已经清晰了,在 foreach 循环中执行 list.remove(item);,对 list 对象的 modCount 值进行了修改,而 list 对象的迭代器的 expectedModCount 值未进行修改,因此抛出了ConcurrentModificationException异常。
二、解决办法
2.1、采用倒序移除
1 | |
输出结果:
1 | |
2.2、fore的解决办法
1 | |
输出结果:
1 | |
2.3、使用迭代器移除
1 | |
输出结果:
1 |
|
2.4、jdk1.8的写法
1 | |
输出结果:
1 |
|
是不是好简单,哈哈!
三、总结
如果开发中需要在集合中移除某个元素,如果jdk是1.8的,建议直接使用2.4方法,如果是低版本,那么建议采用迭代器方法,效率高,性能好!
四、参考
部分内容参考:cdsn那是2008