遍历list过程中调用remove方法

1、普通for循环遍历List删除指定元素,list.remove(index)

java 复制代码
List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六"));
nameList.add("张七");
nameList.add("张八");
for (int i = 0; i < nameList.size(); i++) {
     String name = nameList.get(i);
     System.out.println("当前遍历对象==="+name);
     if (name.startsWith("张")) {
         nameList.remove(i);
     }
}
System.out.println(nameList);

运行结果:

当前遍历对象===张三

当前遍历对象===王五

当前遍历对象===赵六

当前遍历对象===张七

李四,王五,赵六,张八

原因分析:

List调用remove(index)方法后,会移除index位置上的元素,之后的所有元素依次前移,当移除完【张三】时,【李四】变成了数组的第一位,此时的索引应该要index-1才能获取到【李四】。所以每移除一个元素时就需要把index-1,否则原来索引为index+1的元素就无法遍历到。

2、foreach遍历List删除元素

java 复制代码
List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六"));
nameList.add("张七");
nameList.add("张八");
for (String name : nameList) {
    System.out.println("当前遍历对象==="+name);
    if (name.startsWith("张")) {
        nameList.remove(name);
    }
}
System.out.println(nameList);

运行结果:

当前遍历对象===张三

Exception in thread "main" java.util.ConcurrentModificationExceptionat java.util.ArrayListItr,checkForComodification(ArravList. iava:909)at java.util.ArrayListItr,next(ArrayList. java:859)

原因分析:

foreach循环实际上是迭代,使用list.remove(item)方法后,list 对象的modCount值进行了修改,而 list对象的迭代器中的expectedModCount值没有修改,所以抛出了异常

3、正确移除的几种方式

java 复制代码
1、 使用list.removeIf()方法
removeIf()的入参是一个过滤条件,用来判断需要移除的元素是否满足条件。
原理:方法中设置了一个removeSet,把满足条件的元素索引坐标都放入removeSet,然后统一对removeSet中的索引进行移除
示例:将姓张的名字移除掉
List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六"));
nameList.add("张七");
nameList.add("张八");
nameList.removeIf(o->o.startsWith("张"));
System.out.println(nameList);
输出结果:[李四, 王五, 赵六]
2、使用迭代器Iterator移除元素
迭代器是一个链表,直接使用remove操作不会出现问题
示例:同上
List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六"));
nameList.add("张七");
nameList.add("张八");
Iterator<String> iterator = nameList.iterator();
while (iterator.hasNext()) {
    if (iterator.next().startsWith("张")) {
        iterator.remove();
    }
}
System.out.println(nameList);
输出结果:[李四, 王五, 赵六]
3、使用list.removeAll()方法
定义一个需要移除的数组,for循环内将需要移除的元素收集在定义的数组中,for循环结束后直接removeAll()
示例:同上
List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六"));
nameList.add("张七");
nameList.add("张八");
List<String> removeList = new ArrayList<>();
for (String name : nameList) {
    if (name.startsWith("张")) {
        removeList.add(name);
    }
}
nameList.removeAll(removeList);
System.out.println(nameList);
输出结果:[李四, 王五, 赵六]
4、倒序遍历元素然后删除
正序删除元素会移位那我们转变思维倒序遍历
示例:
List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六"));
nameList.add("张七");
nameList.add("张八");
for (int i = nameList.size() - 1; i >= 0; i--) {
    String name = nameList.get(i);
    System.out.println("当前遍历对象===" + name);
    if (name.startsWith("张")) {
        nameList.remove(i);
    }
}
System.out.println(nameList);
输出结果:
相关推荐
小鹏linux5 小时前
Ubuntu 22.04 部署开源免费具有精美现代web页面的Casdoor账号管理系统
linux·前端·ubuntu·开源·堡垒机
在角落发呆6 小时前
Linux转发配置:解锁网络互联的核心密码
linux·运维·网络
齐潇宇6 小时前
Zabbix 7 概述与配置
linux·zabbix·监控告警
江公望8 小时前
Ubuntu htop命令,10分钟讲清楚
linux·服务器
哎呦,帅小伙哦8 小时前
Linux 时间:从原子钟到 clock_gettime 的每一面
linux·运维·服务器
张小姐的猫8 小时前
【Linux】多线程 —— 线程互斥
linux·运维·服务器·c++
YuanDaima20489 小时前
Linux 进阶运维与 AI 环境实战:进程管理、网络排错与 GPU 监控
linux·运维·服务器·网络·人工智能
lolo大魔王10 小时前
Linux 数据文件处理实战:排序、搜索、压缩、归档一站式详解
linux·运维·服务器
starvapour11 小时前
Ubuntu切换到Fcitx5中文输入法
linux·运维·ubuntu
木心术111 小时前
Windows系统下MySQL与AI工具集成方案:数据存储与调用实践
人工智能·windows·mysql