java循环中删除元素

在一般的集合框架中(比如ArrayList),如果要删除集合总的某一条件元素,一般调用的都是迭代器的remove方法。

使用for循环,和增强for循环一般都会抛出ConcurrentModificationException异常。

增强for循环删除元素代码:

List<String> testList = new ArrayList<>();

for(int i = 0;i<10;i++){

testList.add("test : "+i);

}

for (String string : testList) {

System.out.println(string);

testList.remove(string);

}

增强for开始testList数据(modCount=10,size=10):

[test : 0, test : 1, test : 2, test : 3, test : 4, test : 5, test : 6, test : 7, test : 8, test : 9]

第一次执行remove可以正常删除,这时testList数据(modCount=11,size=9):

[test : 1, test : 2, test : 3, test : 4, test : 5, test : 6, test : 7, test : 8, test : 9]

第二次循环的时候就会抛出ConcurrentModificationException异常。

增强for循环其实也是调用的迭代器,具体可以看编译后的文件或者debug循环过程可以看出,而且这个迭代器对于这个for循环

只会在初始化的时候创建,所以以后的每次for循环都会使用同一个迭代器对象。

在迭代器创建的时候,有一个变量:expectedModCount 这个值在迭代器初始化的时候 设置expectedModCount = modCount,

当testList.remove发生的时候,没有办法通知迭代器的expectedModCount发生变化,所以第二次循环获取next的时候,因为checkForComodification

方法校验了这两个值是不是一样的,由于不一致导致抛出ConcurrentModificationException异常。

就像下面的写法一样:

Iterator<String> iterator = testList.iterator();

while(iterator.hasNext()){

String obj = iterator.next(); //获取值,并且使迭代器游标cursor+1

testList.remove(obj); //  throw ConcurrentModificationException

iterator.remove();  //不获取next直接remove会抛出IllegalStateException异常

}


直接使用迭代器的remove可以成功是因为迭代器的每次remove都会设置expectedModCount = modCount,remove方法之前要确保next方法调用。


如果一定要使用循环删除元素,不使用迭代器,可以选择使用CopyOnWriteArrayList 这个可以正常的在循环中删除元素,每次的操作都有数组的copy,性能

会有所下降。

其他的集合类也大部分是这样的情况,所以还是尽量的使用迭代器比较好。



你可能感兴趣的:(java循环中删除元素)