Java 集合遍历中删除元素的正确方法与陷阱

在 Java 开发中,经常会遇到遍历集合并删除特定元素的需求。乍一看,这似乎是一个简单的操作,但如果不注意方式,很容易踩坑。这篇文章将带你理解如何在 Java 中安全地删除集合元素,并避免 ConcurrentModificationException

示例代码

假设我们有一个学生集合 students,需求是遍历集合并删除 id2 的学生,最初代码可能是这样的:

for (Student stu : students) {if (stu.getId() == 2)students.remove(stu);
}

问题:ConcurrentModificationException

运行上述代码时会抛出 ConcurrentModificationException。这是因为 增强 for 循环(即 for-each 循环) 其实是依赖 隐式迭代器 实现的,当循环在迭代时直接修改集合,就会导致迭代器状态不一致,触发此异常。

为什么会出现异常?

for-each 循环中,集合会创建一个迭代器来遍历每个元素。然而,Java 的集合框架设计了修改检查机制,当迭代过程中发现集合被外部修改(如添加或删除元素)时,迭代器会抛出 ConcurrentModificationException。这是为了确保集合的一致性并防止难以追踪的错误。

解决方案:正确的删除方法

为了避免这种异常,我们可以使用以下方法来安全地删除集合中的元素。


方法一:显式使用 Iterator

使用 Iterator 提供的 remove 方法来删除当前元素,这是最推荐的方法。Iterator 提供的 remove 操作是专门设计的,它能安全地删除当前迭代元素,不会导致并发修改异常。

代码示例如下:

Iterator<Student> iterator = students.iterator();
while (iterator.hasNext()) {Student stu = iterator.next();if (stu.getId() == 2) {iterator.remove(); // 安全删除当前元素}
}

在这个例子中,iterator.remove() 方法直接删除当前元素,是在迭代器层级上完成的,因此不会抛出 ConcurrentModificationException


方法二:使用 removeIf(Java 8 及以上版本)

在 Java 8 及更高版本中,集合类引入了 removeIf 方法。它允许通过一个条件(如 Lambda 表达式)来批量删除满足条件的元素,非常简洁。

示例代码如下:

students.removeIf(stu -> stu.getId() == 2);

这行代码会遍历 students 集合,并删除所有 id2 的学生,且不会产生 ConcurrentModificationException。这是因为 removeIf 是由集合实现自身直接提供的,因此可以安全修改集合。


方法三:使用 Stream API 进行过滤

如果不在意是否修改原集合,而是希望获得过滤后的新集合,可以利用 Java 8 的 Stream API。通过 filter 方法,我们可以得到一个不包含目标元素的新集合:

List<Student> filteredStudents = students.stream().filter(stu -> stu.getId() != 2).collect(Collectors.toList());

这里的 filter 方法不会修改原集合 students,而是创建了一个符合条件的副本 filteredStudents。如果业务逻辑允许创建新集合,这是一种非破坏性的好方法。


小结

在 Java 中遍历集合并删除元素时,避免 ConcurrentModificationException 的方法如下:

  1. 显式使用 Iteratorremove 方法:适合在遍历中需要安全删除元素的场景。
  2. 使用 removeIf 方法:适合需要通过条件批量删除元素,语法简洁。
  3. 使用 Stream APIfilter 创建新集合:适合不修改原集合的情况下得到过滤结果。

完整示例代码

以下是完整的示例代码展示如何使用这些方法:

// 示例 1:使用 Iterator 的 remove 方法
Iterator<Student> iterator = students.iterator();
while (iterator.hasNext()) {Student stu = iterator.next();if (stu.getId() == 2) {iterator.remove();}
}// 示例 2:使用 removeIf 方法(Java 8 及以上)
students.removeIf(stu -> stu.getId() == 2);// 示例 3:使用 Stream API 生成新集合(不修改原集合)
List<Student> filteredStudents = students.stream().filter(stu -> stu.getId() != 2).collect(Collectors.toList());

结论

在 Java 中,直接在 for-each 循环中删除集合元素会导致 ConcurrentModificationException。为了避免这个问题,优先使用 显式迭代器的 remove 方法,或 Java 8 引入的 removeIfStream API

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

sed超实用的文本处理工具

sed命令参数表 sed参数说明a在指定行的后面增加新航c替换指定行d删除行-e多次编辑&#xff0c;多次编辑后这样写回文件。sed -i -e /^[[:space:]]*#/d -e /^$/d nginx.confp打印行-r激活拓展正则-n取消默认输出-i静默编辑&#xff0c;屏幕上不显示编辑后的内容&#xff0c;放在…

GPU 环境搭建指南:如何在裸机、Docker、K8s 等环境中使用 GPU

本文主要分享在不同环境&#xff0c;例如裸机、Docker 和 Kubernetes 等环境中如何使用 GPU。 跳转阅读原文&#xff1a;GPU 环境搭建指南&#xff1a;如何在裸机、Docker、K8s 等环境中使用 GPU 1. 概述 仅以比较常见的 NVIDIA GPU 举例&#xff0c;系统为 Linux&#xff0c;…

Vue中父组件通过v-model向子组件传对象参数

描述&#xff1a; Vue中父组件通过v-model向子组件传递一个对象&#xff0c;在子组件实现一个能够对object key-value进行编辑的组件封装。 父组件文件 <form-child v-model"configMap"></form-child>import formChild from /components/formchild.vue i…

mysql数据同步到sql server

准备工作 下载安装sql server express 2019 现在安装SSMS(连接数据库GUI) 安装ssms for mysql 需要注意的是在上面的步骤中首先需要根据指导安装mysql ODBC 设置express sa用户密码登录 --change password for login user "sa"Security > Logins > sa (rig…

如何解决企业业务流程分散的痛点

企业面临的一个普遍问题是业务流程的分散。业务流程分散不仅使得工作效率大幅下降&#xff0c;还增加了出错的风险&#xff0c;影响了企业的整体运营效率。因此&#xff0c;解决这一问题成为了许多企业亟需面对的挑战。 业务流程分散的原因 业务流程分散的根本原因&#xff0…

融入模糊规则的宽度神经网络结构

融入模糊规则的宽度神经网络结构 论文概述创新点及贡献 算法流程讲解模糊规则生成映射节点生成输出预测结果 核心代码复现main.py文件FBLS.py文件 使用方法测试结果示例&#xff1a;使用公开数据集进行本地训练准备数据数据输入模型进行训练实验结果 环境配置资源获取 本文所涉…

SQL常见语法

select * from student; select&#xff1a;选取 from&#xff1a;来源 *&#xff1a;所有栏位 select 姓名&#xff0c;班级&#xff0c;成绩 from students; 选取特定栏位 select 姓名&#xff0c;班级&#xff0c;成绩 from students limit 5;--限制显示拦数 select 姓…

贪心算法-汽车加油

这道题目描述了一个汽车旅行场景&#xff0c;需要设计一个有效的算法来决定在哪几个加油站停车加油&#xff0c;以便最小化加油次数。题目给出了汽车加满油后的行驶距离n公里&#xff0c;以及沿途若干个加油站的位置。我们需要找出一个方案&#xff0c;使得汽车能够完成整个旅程…

yarn报错`warning ..\..\package.json: No license field`:已解决

出现这个报错有两个原因 1、项目中没有配置许可证 在项目根目录package.json添加 {"name": "next-starter","version": "1.0.0",# 添加这一行"license": "MIT", }或者配置私有防止发布到外部仓库 {"priv…

【电子通识】TINA-TI中仿真波形如何配置自动分离曲线?

在实际的TIAN-TI使用中,我们仿真后,输出的波形一般都是叠加的形式输出的。比如下图所示: 有一些更多条曲线且曲线内容不同的仿真,叠加后会更让我们看不清。导致很不方便。 一般这时我们会 选择View->Separate outputs( 分开输出),就可以将不同波形分…

【数据结构】线性表——顺序表

文章目录 一、线性表二、顺序表2.1概念及结构2.2、顺序表接口实现2.2.1、顺序表的动态存储2.2.2、顺序表初始化2.2.3、检查空间判断进行增容2.2.4、顺序表尾插、尾删2.2.5、顺序表头插、头删2.2.6、顺序表查找2.2.7、顺序表在pos位置插入x2.2.8、顺序表删除pos位置的值2.2.9、顺…

【Matlab算法】MATLAB实现基于小波变换的信号去噪(附MATLAB完整代码)

MATLAB实现基于小波变换的信号去噪 结果图前言正文1. 小波变换理论基础1.1 小波变换的数学模型1.2 离散小波变换原理2. 信号去噪方法2.1 去噪算法流程2.2 阈值处理方法3. 核心函数解析3.1 wavedec函数3.2 wthresh函数代码实现4.1 信号生成4.2 小波变换去噪完整代码总结参考文献…

神经网络基础--什么是正向传播??什么是方向传播??

前言 本专栏更新神经网络的一些基础知识&#xff1b;这个是本人初学神经网络做的笔记&#xff0c;仅仅堆正向传播、方向传播进行了讲解&#xff0c;更加系统的讲解&#xff0c;本人后面会更新《李沐动手学习深度学习》&#xff0c;会更有详细讲解;案例代码基于pytorch&#xf…

函数式编程Stream流(通俗易懂!!!)

目录 1.Lambda表达式 1.1 基本用法 1.2 省略规则 2.Stream流 2.1 常规操作 2.1.1 创建流 2.1.2 中间操作 filter map distinct sorted limit ​编辑skip flatMap 2.1.3 终结操作 foreach count max&min collect anyMatch allMatch noneMatch …

AMD-OLMo:在 AMD Instinct MI250 GPU 上训练的新一代大型语言模型。

AMD-OLMo是一系列10亿参数语言模型&#xff0c;由AMD公司在AMD Instinct MI250 GPU上进行训练&#xff0c;AMD Instinct MI250 GPU是一个功能强大的图形处理器集群&#xff0c;它利用了OLMo这一公司开发的尖端语言模型。AMD 创建 OLMo 是为了突出其 Instinct GPU 在运行 “具有…

使用服务器时进行深度学习训练时,本地必须一直保持连接状态吗?

可以直接查看方法&#xff0c;不看背景 1.使用背景2. 方法2.1 screen命令介绍2.2 为什么要使用screen命令2.3 安装screen2.4 创建session2.5 查看session是否创建成功2.6 跳转进入session2.7 退出跑代码的session2.8 删除session 1.使用背景 我们在进行深度学习训练的时候&…

深入了解区块链:Web3的基础架构与发展

在数字时代的浪潮中&#xff0c;区块链技术正逐渐成为Web3的重要基础&#xff0c;重新定义互联网的结构和用户体验。Web3不仅是一个全新的网络阶段&#xff0c;更代表了一种去中心化的理念&#xff0c;强调用户主权和数据隐私。本文将深入探讨区块链在Web3中的基础架构、技术特…

华为大变革?仓颉编程语言会代替ArkTS吗?

在华为鸿蒙生态系统中&#xff0c;编程语言的选择一直是开发者关注的焦点。近期&#xff0c;华为推出了自研的通用编程语言——仓颉编程语言&#xff0c;这引发了关于仓颉是否会取代ArkTS的讨论。本文将从多个角度分析这两种语言的特点、应用场景及未来趋势&#xff0c;探讨仓颉…

【C++笔记】C++三大特性之继承

【C笔记】C三大特性之继承 &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;C笔记 文章目录 【C笔记】C三大特性之继承前言一.继承的概念及定义1.1 继承的概念1.2继承的定义1.3继承基类成员访问方式的变化1.4继承类模板 二.基类和派生类间的转…

Windows搭建流媒体服务并使用ffmpeg推流播放rtsp和rtmp流

文章目录 搭建流媒体服务方式一安装mediamtx启动meidamtx关闭meidamtx 方式二安装ZLMediaKit启动ZLMediaKit关闭ZLMediaKit 安装FFmpeg进行推流使用FFmpeg进行rtmp推流使用VLC播放rtmp流停止FFmpeg的rtmp推流使用FFmpeg进行rtsp推流使用VLC播放rtmp流停止FFmpeg的rtsp推流 本文…