遍历List集合和Map进行修改和删除报java.util.ConcurrentModificationException错误详解
一、异常产生
当我们使用foreach迭代一个ArrayList或者HashMap时,如果尝试对集合做一些修改操作(例如删除元素或新增),可能会抛出java.util.ConcurrentModificationException的异常。
```javapublic static void main(String[] args) {List<User> list=new ArrayList<>();for(int i=0;i<10;i++){User user = new User();user.setMsg("123"+i);user.setName("王总"+i);list.add(user);}list.forEach(item->{if(Objects.equals(item.getMsg(),"1234")){User user = new User();item.setName("456789");CglibUtil.copy(item,user);list.add(user);}});System.out.println(list);}
执行之后会报:

map的例子:```javajcItemMap.forEach((x,items)->{List<FinFreightItemR> finFreightItemRList = items.stream().filter(item -> Objects.equals(item.getAmountFlag(), FinConstant.YesOrNo.YES)).collect(Collectors.toList());if(CollectionUtil.isEmpty(finFreightItemRList)){jcItemMap.remove(x);allItemMap.remove(x);}});

二、java.util.ConcurrentModificationException异常产生的原因
ArrayList的父类AbstarctList中有一个域modCount,每次对集合进行修改(增添元素,删除元素。。。)时都会modCount++.而foreach的背后实现原理其实就是Iterator,等同于注释部分代码。在这里,迭代ArrayList的Iterator中有一个变量expectedModCount,该变量会初始化和modCount相等,但如果接下来对集合进行修改,modCount改变,就会造成expectedModCount !=modCount,此时就会掏出异常java.util.ConcurrentModificationException异常。
过程如下图:

三、异常的解决
1.单线程环境
上面我们已经了解了异常的发送原因,接下我们说一下解决方案。
1.1我们可以使用iterator迭代器进行遍历
Iterator<User> iterator = list.iterator();while(iterator.hasNext()){User user = iterator.next();if(Objects.equals(user.getMsg(),"1234")){iterator.remove();}}System.out.println(list);
细心的朋友会发现Itr中的也有一个remove方法,实质也是调用了ArrayList中的remove,但增加了expectedModCount = modCount;保证了不会抛出java.util.ConcurrentModificationException异常。
但是,这个办法的有两个弊端
1.只能进行remove操作,add、clear等Itr中没有。
2.而且只适用单线程环境。
2、多线程环境
方法一:迭代前加锁,解决了多线程问题,但还是不能进行迭代add、clear等操作。
public class Test12 {static List<String> list = new ArrayList<String>();public static void main(String[] args) {list.add("a");list.add("b");list.add("c");list.add("d");new Thread() {public void run() {Iterator<String> iterator = list.iterator();synchronized (list) {while (iterator.hasNext()) {System.out.println(Thread.currentThread().getName()+ ":" + iterator.next());try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}};}.start();new Thread() {public synchronized void run() {Iterator<String> iterator = list.iterator();synchronized (list) {while (iterator.hasNext()) {String element = iterator.next();if (Objects.equals(element,"c")) {System.out.println(Thread.currentThread().getName()+ ":" + element);iterator.remove();}}}};}.start();}
}
方法二:采用CopyOnWriteArrayList,解决了多线程问题,同时可以add、clear等操作
public class Test12 {static List<String> list = new CopyOnWriteArrayList<>();public static void main(String[] args) throws InterruptedException {list.add("a");list.add("b");list.add("c");list.add("d");new Thread() {public void run() {Iterator<String> iterator = list.iterator();synchronized (list) {while (iterator.hasNext()) {System.out.println(Thread.currentThread().getName()+ ":" + iterator.next());try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}};}.start();new Thread() {public synchronized void run() {Iterator<String> iterator = list.iterator();synchronized (list) {while (iterator.hasNext()) {String element = iterator.next();if (Objects.equals(element,"c")) {System.out.println(Thread.currentThread().getName()+ ":" + element);list.remove(element);list.add("123456");}}}};}.start();Thread.sleep(5000);System.out.println(list);}
}
CopyOnWriteArrayList也是一个线程安全的ArrayList,其实现原理在于,每次add或remove等所有的操作都是重新创建一个新的数组,再把引用指向新的数组。
对于HashMap的迭代删除是一样的



相关文章:
遍历List集合和Map进行修改和删除报java.util.ConcurrentModificationException错误详解
一、异常产生 当我们使用foreach迭代一个ArrayList或者HashMap时,如果尝试对集合做一些修改操作(例如删除元素或新增),可能会抛出java.util.ConcurrentModificationException的异常。 javapublic static void main(String[] args)…...
Android从一个APP跳转到另外一个APP
1、从当前APP去全新启动另外一个目标APP(非覆盖同一个进程): 启动另外一个目标APP(非覆盖原来APP的方式) 1、当前APP加入获取权限声明:(不加人权限检查,没法启动目标app࿰…...
我的创作纪念日——创作者2年
机缘 我最初使用CSDN估计是在2014年左右,当时还在读研,除了在当时比较有名的BBS例如小木虫上进行学术交流外,我发现很多问题百度后,都会转到CSDN,而且文章内容颇为专业,很多问题也都有专业的回答ÿ…...
大数据之LibrA数据库系统告警处理(ALM-12032 ommdba用户或密码即将过期)
告警解释 系统每天零点开始,每8小时检测当前系统中ommdba用户和密码是否过期,如果用户或密码即将在15天内过期,则发送告警。 当系统中ommdba用户过期的期限修改或密码重置,告警恢复。 告警属性 告警ID 告警级别 可自动清除 …...
C_3练习题
一、单项选择题(本大题共20小题,每小题2分,共40分。在每小题给出的四个备选项中,选出一个正确的答案,并将所选项前的字母填写在答题纸的相应位置上。) 1.下列叙述中正确的是()。 A.用C程序实现的算法必须要有输入和输出操作 B.用C程序实现的…...
CentOS7 安装Jenkins 2.414.3 详细教程
目录 1、前提条件硬件软件-java11安装 2、安装jenkins3、启动jenkins配置用户和用户组配置JAVA_HOME 4、配置Jenkins一直处于启动状态5、测试Jenkins是否可以访问以及配置6、访问Jenkins系统 1、前提条件 硬件 内存 4G ; 硬盘 20G 软件-java11安装 上传文件jdk-11.0.21_lin…...
chatglm3-6b记录问答对
# 打开文件,第二个参数是打开文件的模式,a代表追加,也就是说,打开这个文件之后直接定位到文件的末尾 file open(chatlog.txt, "a") # 写入数据 file.write(ask:prompt_text\n) file.write(response:response\n) # 关闭文件 fil…...
k8s ingress 代理 mysql 3306端口
helm 安装 ingress-nginx helm upgrade --install ingress-nginx ingress-nginx \--repo https://kubernetes.github.io/ingress-nginx \--namespace ingress-nginx --create-namespace执行命令 kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-ngin…...
Informix管理共享内存
1、查看共享内存使用情况 [informixREHL4 ~]$ onstat -g seg IBM Informix Dynamic Server Version 11.50.UC4 -- On-Line -- Up 00:38:21 -- 144144 Kbytes Segment Summary: id key addr size ovhd class blkused blkfree 393226 …...
Webpack 中 Plugin 的作用是什么?常用 plugin 有哪些?
说说webpack中常见的Plugin?解决了什么问题?- 题目详情 - 前端面试题宝典 1、plugin 的作用 Plugin 是一种计算机应用程序,它和主应用程序互相交互,以提供特定的功能。 是一种遵循一定规范的应用程序接口编写出来的程序&#…...
CSRF(跨站请求伪造)攻击演示
目录 CSRF(跨站请求伪造)攻击演示CSRF 是什么CSRF 演示项目代码CSRF 演示过程服务启动演示 CSRF(跨站请求伪造)攻击演示 CSRF 是什么 CSRF(Cross-Site Request Forgery)跨站请求伪造,是一种网络安全攻击,其目标是利用被攻击者在…...
图解三傻排序 选择排序、冒泡排序、插入排序
(1)选择排序 // 交换 void swap(int arr[], int i, int j) {int tmp arr[i];arr[i] arr[j];arr[j] tmp; }// 选择排序 void selectionSort(int arr[],int len) {if (len < 2) return;for (int minIndex, i 0; i < len - 1; i) {minIndex i;f…...
【数据结构】树与二叉树(六):二叉树的链式存储
文章目录 5.1 树的基本概念5.1.1 树的定义5.1.2 森林的定义5.1.3 树的术语5.1.4 树的表示 5.2 二叉树5.2.1 二叉树1. 定义2. 特点3. 性质引理5.1:二叉树中层数为i的结点至多有 2 i 2^i 2i个,其中 i ≥ 0 i \geq 0 i≥0。引理5.2:高度为k的二叉…...
后端Java日常实习生面试(2023年11月10日)
面试岗位为:Java 后端开发实习生 面试时长:30分钟 面试时间:2023年11月10日 首先介绍一下项目吧 这里介绍时有一个失误,没有主动把屏幕共享给打开,因为我在面试之前已经在 processon 上画好了项目的流程图…...
使用iperf3在macOS上进行网络性能测试
iperf3是一个用于测量网络性能的工具,它可以帮助你了解两台服务器之间的带宽和延迟。本博客将指导你在macOS上安装iperf3,并展示如何连接服务器进行网络性能测试。 步骤1:安装Homebrew 如果你尚未安装Homebrew,可以通过以下步骤…...
09-MySQL主从复制
01-主从复制原理 MySQL主从复制是一种用于实现数据备份、读写分离和扩展性的技术。它基于二进制日志(Binary Log)来将主数据库上的更改操作同步到一个或多个从数据库。 MySQL主从复制的基本原理如下: 主服务器(Master࿰…...
virtualBox虚拟机局域网访问配置
在VirtualBox中,桥接网络是一种网络连接类型,它允许虚拟机连接到物理网络上的路由器或交换机,在物理网络上获得独立的网络地址和访问权限。 一、设置VirtualBox桥接网络的步骤: 打开VirtualBox软件,并选择你想要配置…...
IDEA高效编程快捷键
IDEA高效编程快捷键 for循环快捷键 快速生成for循环 foriTABfor (int i 0; i < ; i) {}在for循环中使用索引 iterTABfor (String s : list) {}在for循环中进行if条件判断 ifnTABif (list null) {} soutTAB快捷键 System.out.println();psfEnter快捷键 p…...
nginx实现vue和后端的双机负载
nginx配置文件,项目是前后端分离的,前端vue,后端springboot 前端使用nginx实现双机负载,前端的访问端口是95280,后端2个服务实例的端口分部为9098,9099 nginx.conf的配置文件 #user root; worker_processes 1;#err…...
ARMday03(寄存器读写、栈、程序状态寄存器、软中断和异常、混合编程)
单寄存器内存读写指令 将一个寄存器中的数值写入到内存,或者从内存中读取数据放在某一个指定寄存器中 指令码和功能 1.向内存中写: str{条件码} 目标寄存器,[目标地址]:将目标寄存器的4字节数值写入到目标地址为首地址的空间中 strh{条件码…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...
jdbc查询mysql数据库时,出现id顺序错误的情况
我在repository中的查询语句如下所示,即传入一个List<intager>的数据,返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致,会导致返回的id是从小到大排列的,但我不希望这样。 Query("SELECT NEW com…...
CppCon 2015 学习:Time Programming Fundamentals
Civil Time 公历时间 特点: 共 6 个字段: Year(年)Month(月)Day(日)Hour(小时)Minute(分钟)Second(秒) 表示…...
PydanticAI快速入门示例
参考链接:https://ai.pydantic.dev/#why-use-pydanticai 示例代码 from pydantic_ai import Agent from pydantic_ai.models.openai import OpenAIModel from pydantic_ai.providers.openai import OpenAIProvider# 配置使用阿里云通义千问模型 model OpenAIMode…...
CVE-2023-25194源码分析与漏洞复现(Kafka JNDI注入)
漏洞概述 漏洞名称:Apache Kafka Connect JNDI注入导致的远程代码执行漏洞 CVE编号:CVE-2023-25194 CVSS评分:8.8 影响版本:Apache Kafka 2.3.0 - 3.3.2 修复版本:≥ 3.4.0 漏洞类型:反序列化导致的远程代…...
