本文主要介绍,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