List的remove()方法详解

news/2024/10/11 2:18:02

https://blog.csdn.net/anxin_hw/article/details/128312846

一、错误使用场景

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

示例:将姓张的名字移除掉

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删除元素

示例:同上

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);

  输出结果:

 

原因分析:

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

3、直接使用list.remove(object)

示例: 将张三从数组中移除

List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六"));
nameList.add("张三");
nameList.add("张三");
nameList.remove("张三");
System.out.println(nameList);

  

输出结果:[李四, 王五, 赵六, 张三, 张三]

原因分析:

list.remove(object)的逻辑和list.remove(index)大致相同:元素依次遍历,数组中存在与入参对象相等的元素就移除,之后的所有元素依次前移,返回true,若不存在与入参相等的元素,返回false。

二、正确使用方法

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);

  输出结果:

 

三、总结

1、使用普通for循环删除元素时需要注意索引会变化的问题

2、list删除元素时建议使用迭代器Iterator或者removeIf()方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/27565.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

软考备考1

【BV1Qc411G7fB】考试形式 考45分就行上午-计算机与软件工程知识-150分钟,笔试,选择题-75分还有5分时专业英语,,一篇文章挖5个空下午-软件设计-150分钟-笔试-简答题-75分三个复习阶段考点理论学习——建立理论框架 题型全覆盖——考试全部题型了然于胸 真题强化训练——适应…

AWVS

工具说明 Acunetix Web Vulnerability Scanner(简称AWVS)是一款知名的Web网络漏洞扫描工具,他通过网络爬虫测试你的网站安全,检测流行安全漏洞。 AWVS可以通过SQL注入攻击、XSS(跨站脚本攻击)、目录遍历、代码执行等漏洞来审核Web应用程序的安全性并输出扫描报告。相对于…

树状数组(二维偏序)

题目链接 https://leetcode.cn/problems/maximum-sum-queries/description/ 题目大意题目思路 二维偏序问题 -> 一维排序,一维树状数组! 题目代码 class Solution { public:int sz;vector<int> tr;int lowbit(int x){return x & -x;}void update(int x,int k){f…

游戏排名算法:Elo、Glicko、TrueSkill

Elo rating system Elo等级分制度(英语:Elo rating system)是指由匈牙利裔美国物理学家Arpad Elo创建的一个衡量各类对弈活动水平的评价方法,是当今对弈水平评估公认的权威标准。 两个选手(player)在排名系统的不同,可以用来预测比赛结果。两个具有相同排名(rating)的…

lxc容器没有cron的解决办法

简介 我经常使用cron定时脚本来更新我的cloudflare ddns。 最近想着把pve上跑着的fedora,切换到lxc容器试试。 结果就遇到了没有cron的尴尬。 安装 dnf search crontab dnf install cronatbs启动 systemctl start crond 自启动 systemctl enable crond 小结 主要就是search找一…

视频局部打马赛克

给视频局部打马赛克,用手机APP剪映,操作如下: 1、打开剪映APP,点击“开始创作”,选择需要打马的视频; 2、点击下方“特效”工具-->选“画面特效”-->“基础”-->搜索“马赛克”,添加马赛克特效; 3、成功添加“马赛克”特效到创作区,根据自己需要拉长或缩短…

计算机网络体系结构

一、计算机网络概念 1、计算机网络定义 将分散的、具有独立功能的计算机系统,通过通信设备与线路连接起来,由功能完善的软件实现资源共享的系统。 与多终端系统的区别:传统多终端系统是由中央处理器、多个联机终端及一个多用户操作系统组成。终端本身不具备独立的数据处理能…

文件(夹)批量重命名数字、字母、日期、中文数字大写小写

首先,需要用到的这个工具:度娘网盘 提取码:qwu2 蓝奏云 提取码:2r1z 目标是重命名下面5个文件(也可以是文件夹等,任意),从大写中文数字“贰”开始 打开工具,找到“文件批量复制”版块,快捷键Ctrl+5 找到右下角重命名按钮,点击打开 把那5个要重命名的文件拖入(也…