`
暗黑小菠萝
  • 浏览: 45931 次
  • 性别: Icon_minigender_2
  • 来自: 大连
社区版块
存档分类
最新评论

ArrayList遍历删除陷阱

    博客分类:
  • Java
阅读更多
如何对ArrayList进行删除操作:

remove(int index);
remove(Object o);
removeAll(Collection<?> c);

用以上三个方法是可以正常使用的,但对ArrayList进行遍历删除元素时候需要格外注意:

List<String> testList = new ArrayList<String>();
testList.add("1");
testList.add("2");
testList.add("3");
testList.add("4");
testList.add("5");
testList.add("6");

分别采用三种方式遍历删除
①for循环
for(int i = 0 ; i < testList.size() ; i++){
	testList.remove(i);
}

for(String elem : testList){
	System.out.println(elem);
}

结果:


②foreach循环
for(String elem : testList){
	testList.remove(elem);
}

for(String elem : testList){
	System.out.println(elem);
}

结果:


③iterator循环
Iterator<String> it = testList.iterator();
while(it.hasNext()){
	it.next();
	it.remove();
}

for(String elem : testList){
	System.out.println(elem);
}

结果:空白(说明正常删除了全部元素)

下面对上面三种方式进行解析:
①for循环
因为for循环每次删除的是testList.remove(i);
当i=0;时testList.remove(0);删除掉了第一个元素,此时testList.size()大小为5。
当i=1;时testList.remove(1);删除掉此时testList中的第二个元素,略过了第一个元素。之后testList.size()大小为4。
当i=2;时testList.remove(2);删除掉此时testList中的第三个元素,略过了第1,2个元素。之后testList.size()大小为3。
当i=3;时i=testList.size(); for循环结束。所以并不能够完全删除掉整改ArrayList。
需要改写一下这个方法:
int length = testList.size();
for(int i = 0; i< length; i++){
	String t = testList.get(0);
	testList.remove(0);
}

此时就能够删除掉list的全部元素。

②foreach循环
java中的foreach循环其实就是根据list对象创建一个Iterator对象,用这个迭代对象来遍历testList,相当于list对象将元素的遍历托付给Iterator,如果要进行删除或者增加需要通过Iterator,直接对list进行删除时,Iterator会抛出ConcurrentModificationException异常
抛出异常的源码是:
final void checkForComodification() {
        if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
}

modCount是指这个list对象从new出来到现在被修改次数,当调用List的add或者remove方法的时候,这个modCount都会自动增减;
expectedModCount是指Iterator现在期望这个list被修改的次数是多少次。
iterator创建的时候modCount被赋值给了expectedModCount,但是调用list的add和remove方法的时候不会同时自动增减expectedModCount,这样就导致两个count不相等,从而抛出异常。

在ArrayList的所有涉及结构变化的方法中都增加modCount的值,包括:add()、remove()、addAll()、clear()等,这些方法每调用一次,modCount的值就加1。

③Iterator循环
因为是借助Iterator来删除list的元素,所以不会有问题,如果循环中使用list本身来删除同意会抛异常。


综上,推荐使用改进的第一种和第三种方式来迭代循环删除ArrayList
  • 大小: 8.5 KB
  • 大小: 23.3 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics