前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何在遍历集合时删除元素

如何在遍历集合时删除元素

原创
作者头像
真率
发布2024-08-27 10:50:07
1100
发布2024-08-27 10:50:07
举报
文章被收录于专栏:Java

概述

对java.util包下的集合类型来说,如果在通过for-each循环进行遍历时,对集合进行修改操作(删除、添加、修改元素),很多情况下会抛出ConcurrentModificationException异常[1]。这是因为for-each循环是通过迭代器的方式进行的遍历。而该包下的迭代器都属于fail-fast迭代器[2],即不允许在遍历的同时,对集合进行修改,因为这样会导致不确定的遍历结果。例如:

代码语言:java
复制
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");

for (String s : list) {
    if ("c".equals(s)) {
        list.remove(s);
    }
}

原理

集合内部有一个modCount属性,用于记录集合被修改的次数,而迭代器作为集合的内部类,有一个expectedModCount属性。每次迭代时都会实例化一个迭代器,实例化时expectedModCount等于modCount. 如果在迭代进行中,调用了集合的remove、add等方法,modCount就会增加,而迭代器中的expectedModCount仍然保持不变。而迭代中每次通过next方法获取下一个元素时,都会检查这两个值是否相等,如不相等就会抛出ConcurrentModificationException.

解决方案

不推荐在遍历的同时对集合进行修改,可新建一个集合,用于保存修改,而不是直接在原集合上修改。但若是出于代码简洁的目的,想要实现在遍历时删除某个元素,可通过以下方式实现:

1. 通过迭代器删除元素

代码语言:java
复制
Iterator<String> itr = list.iterator();
while (itr.hasNext()) {
    String s = itr.next();
    if ("c".equals(s)) {
        itr.remove();
    }
}

2. 通过stream删除元素

代码语言:java
复制
List<String> list = list.stream().filter(s -> !"c".equals(s)).collect(Collectors.toList());

3. 通过removeIf方法删除元素

代码语言:java
复制
list.removeIf(s -> "c".equals(s));  //语法糖,removeIf本质是通过迭代器进行删除

[1]: 即便不抛异常,也无法保证遍历结果的准确性

[2]: fail-fast是一种通用的设计思想,指一旦检测到可能发生错误,就马上抛出异常,并终止程序执行

参考文献


https://www.baeldung.com/java-fail-safe-vs-fail-fast-iterator

https://developer.aliyun.com/article/1009062

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 原理
  • 解决方案
    • 1. 通过迭代器删除元素
      • 2. 通过stream删除元素
        • 3. 通过removeIf方法删除元素
          • 参考文献
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档