为什么iterator,foreach遍历时不能进行remove操作?

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class TestMain {
    public static void main(String[] args) {
        ArrayList<String> array = new ArrayList<String>();
        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"不会报错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class TestMain {
    public static void main(String[] args) {
        ArrayList<String> array = new ArrayList<String>();
        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

③ 索引删除元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class TestMain {
    public static void main(String[] args) {
        ArrayList<String> array = new ArrayList<String>();
        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

 

④ 迭代器删除元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void main(String[] args) {
 
        ArrayList<String> array = new ArrayList<>();
        array.add("cc");
        array.add("aa");
        array.add("bb");
        array.add("ee");
 
        Iterator<String> iterator = array.iterator();
        while (iterator.hasNext()){
            String e = iterator.next();
            if("bb".equals(e)){
                iterator.remove();
            }
        }    System.out.println(array.size());}console:  3

从上述执行结果可以得出:

① foreach遍历删除后,下一个循环会报错,源码如下红色字体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
   // remove操作导致modCount++   private void fastRemove(int index) {         modCount++;
     int numMoved = size - index - 1;
     if (numMoved > 0)
         System.arraycopy(elementData, index+1, elementData, index,
                          numMoved);
     elementData[--size] = null; // clear to let GC do its work
 }    // 删除元素后,遍历下一个元素会先校验,不通过,报错    public E next() {
        checkForComodification();
        int i = cursor;
        if (i >= size)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;
        return (E) elementData[lastRet = i];
    }
 
final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }

 

② foreach遍历删除后,未报错?

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

 

 

③ for循环删除,不会报错,按照索引删除

 

④ 迭代器的方式遍历,iterator.remove方法删除

 

 总结:  1 foreach遍历,iterator遍历都不能在遍历的过程中使用list.remove或list.add操作,会报并发修改异常,遍历删除后加个break即可解决。

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

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

以上属于个人心得,不对之处还望大佬指出。  

 

posted @   李勇888  阅读(4572)  评论(3编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示