我是靠谱客的博主 义气外套,最近开发中收集的这篇文章主要介绍java foreach iterator remove_为什么iterator,foreach遍历时不能进行remove操作?,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Exception in thread "main" java.util.ConcurrentModificationException 并发修改异常引发的思考!

1 foreach循环删除元素

①list遍历删除元素时会报错,比如下面删除字符串"aa",也有遍历不报错的例子,看下面的例子

public class TestMain {

public static void main(String[] args) {

ArrayList array = new ArrayList();

array.add("cc");

array.add("aa");

array.add("bb");

array.add("aa");

for (String str : array) {

if("aa".equals(str)){

array.remove(str);

}

}

System.out.println(array.size());

}

}

console: java.util.ConcurrentModificationException

②下面删除字符串"aa"不会报错

public class TestMain {

public static void main(String[] args) {

ArrayList array = new ArrayList();

array.add("cc");

array.add("aa");

array.add("bb");

for (String str : array) {

if("aa".equals(str)){

array.remove(str);

}

}

System.out.println(array.size());

}

}

console : 2

提出问题:为什么上面都是遍历删除,第二个确没有报错呢?

结论:其实原因很简单,因为第二个例子没有走iterator的next方法,删除了字符串"aa"之后,执行hasNext方法返回false直接退出遍历了,hasNext中就是判断cursor != size;此时的cursor是2,而size正好也是2,所以退出了遍历。

而第一个例子删除字符串"aa"之后,cursor=2,size=3,所以hasNext方法返回的true,会执行next方法。

注:只要遍历中remove了,expectedModCount和modCount就不相等了。

注2:cursor 就类似游标,这里表示第几次,size就是元素个数

同理:iterator的形式遍历同foreach。

2 上面都是通过foreach的方式进行的,如果用普通for循环会怎么样

public class TestMain {

public static void main(String[] args) {

ArrayList array = new ArrayList();

array.add("cc");

array.add("aa");

array.add("bb");

array.add("aa");

for(int i = 0;i < array.size();i++){

if("aa".equals(array.get(i))){

array.remove(i);

}

}

System.out.println(array.size());

}

}

console: 2

结论: 普通for循环可以正常删除,他是根据索引进行删除的,所以没有影响。

根据报错信息可以看到是进入checkForComodification()方法的时候报错了,也就是说modCount != expectedModCount。具体的原因,是在于foreach方式遍历元素的时候,是生成iterator,然后使用iterator遍历。在生成iterator的时候,

会保存一个expectedModCount参数,这个是生成iterator的时候List中修改元素的次数。如果你在遍历过程中删除元素,List中modCount就会变化,如果这个modCount和exceptedModCount不一致,就会抛出异常,这个是为了安全的考虑。

看看list的remove源码:

1 private void fastRemove(intindex) {2 modCount++;3 int numMoved = size - index - 1;4 if (numMoved > 0)5 System.arraycopy(elementData, index+1, elementData, index,6 numMoved);7 elementData[--size] = null; //clear to let GC do its work

8 }

remove操作导致modCount++

private class Itr implements Iterator{int cursor; //index of next element to return

int lastRet = -1; //index of last element returned; -1 if no such

int expectedModCount =modCount;public booleanhasNext() {return cursor !=size;

}publicE next() {

checkForComodification();try{

E next=get(cursor);

lastRet= cursor++;returnnext;

}catch(IndexOutOfBoundsException e) {

checkForComodification();throw newNoSuchElementException();

}

}final voidcheckForComodification() {if (modCount !=expectedModCount)throw newConcurrentModificationException();

}

总结:  1 foreach遍历,iterator遍历都不能在遍历的过程中使用list.remove或list.add操作,会报并发修改异常。

2 iterator遍历过程中如果需要删除可以使用iterator提供的remove()方法。

3 遍历根据元素索引删除是可行的。

以上属于个人心得,不对之处还望大佬指出,如果对你有帮助会更加激励我。

最后

以上就是义气外套为你收集整理的java foreach iterator remove_为什么iterator,foreach遍历时不能进行remove操作?的全部内容,希望文章能够帮你解决java foreach iterator remove_为什么iterator,foreach遍历时不能进行remove操作?所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部