当前位置: 首页 > news >正文

遍历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时&#xff0c;如果尝试对集合做一些修改操作&#xff08;例如删除元素或新增&#xff09;&#xff0c;可能会抛出java.util.ConcurrentModificationException的异常。 javapublic static void main(String[] args)…...

Android从一个APP跳转到另外一个APP

1、从当前APP去全新启动另外一个目标APP&#xff08;非覆盖同一个进程&#xff09;&#xff1a; 启动另外一个目标APP&#xff08;非覆盖原来APP的方式&#xff09; 1、当前APP加入获取权限声明&#xff1a;&#xff08;不加人权限检查&#xff0c;没法启动目标app&#xff0…...

我的创作纪念日——创作者2年

机缘 我最初使用CSDN估计是在2014年左右&#xff0c;当时还在读研&#xff0c;除了在当时比较有名的BBS例如小木虫上进行学术交流外&#xff0c;我发现很多问题百度后&#xff0c;都会转到CSDN&#xff0c;而且文章内容颇为专业&#xff0c;很多问题也都有专业的回答&#xff…...

大数据之LibrA数据库系统告警处理(ALM-12032 ommdba用户或密码即将过期)

告警解释 系统每天零点开始&#xff0c;每8小时检测当前系统中ommdba用户和密码是否过期&#xff0c;如果用户或密码即将在15天内过期&#xff0c;则发送告警。 当系统中ommdba用户过期的期限修改或密码重置&#xff0c;告警恢复。 告警属性 告警ID 告警级别 可自动清除 …...

C_3练习题

一、单项选择题(本大题共20小题&#xff0c;每小题2分&#xff0c;共40分。在每小题给出的四个备选项中&#xff0c;选出一个正确的答案,并将所选项前的字母填写在答题纸的相应位置上。) 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记录问答对

# 打开文件,第二个参数是打开文件的模式&#xff0c;a代表追加&#xff0c;也就是说&#xff0c;打开这个文件之后直接定位到文件的末尾 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&#xff1f;解决了什么问题&#xff1f;- 题目详情 - 前端面试题宝典 1、plugin 的作用 Plugin 是一种计算机应用程序&#xff0c;它和主应用程序互相交互&#xff0c;以提供特定的功能。 是一种遵循一定规范的应用程序接口编写出来的程序&#…...

CSRF(跨站请求伪造)攻击演示

目录 CSRF(跨站请求伪造)攻击演示CSRF 是什么CSRF 演示项目代码CSRF 演示过程服务启动演示 CSRF(跨站请求伪造)攻击演示 CSRF 是什么 CSRF&#xff08;Cross-Site Request Forgery&#xff09;跨站请求伪造&#xff0c;是一种网络安全攻击&#xff0c;其目标是利用被攻击者在…...

图解三傻排序 选择排序、冒泡排序、插入排序

&#xff08;1&#xff09;选择排序 // 交换 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&#xff1a;二叉树中层数为i的结点至多有 2 i 2^i 2i个&#xff0c;其中 i ≥ 0 i \geq 0 i≥0。引理5.2&#xff1a;高度为k的二叉…...

后端Java日常实习生面试(2023年11月10日)

面试岗位为&#xff1a;Java 后端开发实习生 面试时长&#xff1a;30分钟 面试时间&#xff1a;2023年11月10日 首先介绍一下项目吧 这里介绍时有一个失误&#xff0c;没有主动把屏幕共享给打开&#xff0c;因为我在面试之前已经在 processon 上画好了项目的流程图&#xf…...

使用iperf3在macOS上进行网络性能测试

iperf3是一个用于测量网络性能的工具&#xff0c;它可以帮助你了解两台服务器之间的带宽和延迟。本博客将指导你在macOS上安装iperf3&#xff0c;并展示如何连接服务器进行网络性能测试。 步骤1&#xff1a;安装Homebrew 如果你尚未安装Homebrew&#xff0c;可以通过以下步骤…...

09-MySQL主从复制

01-主从复制原理 MySQL主从复制是一种用于实现数据备份、读写分离和扩展性的技术。它基于二进制日志&#xff08;Binary Log&#xff09;来将主数据库上的更改操作同步到一个或多个从数据库。 MySQL主从复制的基本原理如下&#xff1a; 主服务器&#xff08;Master&#xff0…...

virtualBox虚拟机局域网访问配置

在VirtualBox中&#xff0c;桥接网络是一种网络连接类型&#xff0c;它允许虚拟机连接到物理网络上的路由器或交换机&#xff0c;在物理网络上获得独立的网络地址和访问权限。 一、设置VirtualBox桥接网络的步骤&#xff1a; 打开VirtualBox软件&#xff0c;并选择你想要配置…...

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配置文件&#xff0c;项目是前后端分离的&#xff0c;前端vue&#xff0c;后端springboot 前端使用nginx实现双机负载&#xff0c;前端的访问端口是95280&#xff0c;后端2个服务实例的端口分部为9098,9099 nginx.conf的配置文件 #user root; worker_processes 1;#err…...

ARMday03(寄存器读写、栈、程序状态寄存器、软中断和异常、混合编程)

单寄存器内存读写指令 将一个寄存器中的数值写入到内存&#xff0c;或者从内存中读取数据放在某一个指定寄存器中 指令码和功能 1.向内存中写&#xff1a; str{条件码} 目标寄存器,[目标地址]&#xff1a;将目标寄存器的4字节数值写入到目标地址为首地址的空间中 strh{条件码…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...

Windows电脑能装鸿蒙吗_Windows电脑体验鸿蒙电脑操作系统教程

鸿蒙电脑版操作系统来了&#xff0c;很多小伙伴想体验鸿蒙电脑版操作系统&#xff0c;可惜&#xff0c;鸿蒙系统并不支持你正在使用的传统的电脑来安装。不过可以通过可以使用华为官方提供的虚拟机&#xff0c;来体验大家心心念念的鸿蒙系统啦&#xff01;注意&#xff1a;虚拟…...

前端调试HTTP状态码

1xx&#xff08;信息类状态码&#xff09; 这类状态码表示临时响应&#xff0c;需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分&#xff0c;客户端应继续发送剩余部分。 2xx&#xff08;成功类状态码&#xff09; 表示请求已成功被服务器接收、理解并处…...

深入浅出WebGL:在浏览器中解锁3D世界的魔法钥匙

WebGL&#xff1a;在浏览器中解锁3D世界的魔法钥匙 引言&#xff1a;网页的边界正在消失 在数字化浪潮的推动下&#xff0c;网页早已不再是静态信息的展示窗口。如今&#xff0c;我们可以在浏览器中体验逼真的3D游戏、交互式数据可视化、虚拟实验室&#xff0c;甚至沉浸式的V…...

Yii2项目自动向GitLab上报Bug

Yii2 项目自动上报Bug 原理 yii2在程序报错时, 会执行指定action, 通过重写ErrorAction, 实现Bug自动提交至GitLab的issue 步骤 配置SiteController中的actions方法 public function actions(){return [error > [class > app\helpers\web\ErrorAction,],];}重写Error…...