进阶JAVA篇- Collcetions 工具类与集合的并发修改异常问题
目录
1.0 集合的并发修改问题
1.1 如何解决集合的并发修改问题
2.0 Collcetions 工具类的说明
1.0 集合的并发修改问题
我们可以简单的认为,就是使用迭代器遍历集合时,又同时在删除集合中的数据,程序就会出现并发修改异常的错误。
代码如下:
import java.util.ArrayList; import java.util.Iterator; import java.util.List;public class Abnormal {public static void main(String[] args) {//创建对象,再添加数据List<String> list = new ArrayList<>();list.add("张三");list.add("陈七");list.add("李麻子");list.add("李四");list.add("王五");//利用迭代器进行遍历,先创建迭代器Iterator<String> iterator = list.iterator();while (iterator.hasNext()){String a = iterator.next();if (a.contains("李")){list.remove(a);}}System.out.println(list);} }运行结果如下:
像以上情况,一边遍历的时候去删除数据,直接会报错,原因是因为集合是一个可变的容器,每删一个数据,容器的大小都会改变,那么数据存放的位置也会相应的改变。迭代器遍历可能不好理解,我们就换成普通的 for 循环,但是两者的出现的 Bug 是一样的。
代码如下:
import java.util.ArrayList; import java.util.List;public class Text_For {public static void main(String[] args) {//创建对象,再添加数据List<String> list = new ArrayList<>();list.add("张三");list.add("陈七");list.add("李麻子");list.add("李四");list.add("王五");for (int i = 0; i < list.size(); i++) {String a = list.get(i);if (a.contains("李")){list.remove(a);}}System.out.println(list);} }运行结果如下:
发现用 for 循环竟然不报错,原因可能是没有用迭代器遍历严谨吧,以上的两种代码的效果都是一样的,会出现 Bug ,就是本来要删除带 ”李“ 的名字,但是发现名字还有一个”李四“,没有被删除,那是什么原因呢?
直接会把 ”李四“ 忽略掉,这就是这出现 Bug 的地方。
1.1 如何解决集合的并发修改问题
对于用普通的 for 循环来遍历的代码来说可以有两种方法;第一个方法就是每一次删除数据的时候,都要进行 i--; 第二方法就是从尾开始遍历。
代码如下:
第一种方法
import java.util.ArrayList; import java.util.List;public class Text_For {public static void main(String[] args) {//创建对象,再添加数据List<String> list = new ArrayList<>();list.add("张三");list.add("陈七");list.add("李麻子");list.add("李四");list.add("王五");for (int i = 0; i < list.size(); i++) {String a = list.get(i);if (a.contains("李")){list.remove(a);i--;}}System.out.println(list);} }运行结果如下:
成功把”李四“也删除掉了。
第二种方法
import java.util.ArrayList; import java.util.List;public class Text_For {public static void main(String[] args) {//创建对象,再添加数据List<String> list = new ArrayList<>();list.add("张三");list.add("陈七");list.add("李麻子");list.add("李四");list.add("王五");for (int i = list.size() - 1; i >= 0; i--) {String a = list.get(i);if (a.contains("李")){list.remove(a);}}System.out.println(list);} }运行结果如下:
一样也可以把”李四“删除掉。
对于用迭代器来遍历的代码来说,只能把集合对象.remove(String str) 换成迭代器对象.remove() 。
代码如下:
import java.util.ArrayList; import java.util.Iterator; import java.util.List;public class Abnormal {public static void main(String[] args) {//创建对象,再添加数据List<String> list = new ArrayList<>();list.add("张三");list.add("陈七");list.add("李麻子");list.add("李四");list.add("王五");//利用迭代器进行遍历,先创建迭代器Iterator<String> iterator = list.iterator();while (iterator.hasNext()){String a = iterator.next();if (a.contains("李")){iterator.remove();}}System.out.println(list);} }运行结果如下:
也是可以的。
对于增强 for 循环还有利用 Lambda 表达式的循环都不可以用来一边遍历集合,一边删除数据,无法解决集合的并发修改异常。
2.0 Collcetions 工具类的说明
是一个用来操作集合的工具类。
以代码为例来介绍具体的静态方法:
import java.util.ArrayList; import java.util.Collections; import java.util.List;public class Text_Collections {public static void main(String[] args) {String s1 = "李四";String s2 = "张三";String s3 = "王五";String s4 = "张麻子";List<String> list = new ArrayList<>();//1. addAll() 为集合批量添加数据Collections.addAll(list,s1,s2,s3,s4);System.out.println(list);//输出结果为:[李四, 张三, 王五, 张麻子]//2. shuffle() 打乱list集合中的元素顺序Collections.shuffle(list);System.out.println(list);//输出结果为:[王五, 张麻子, 李四, 张三]//3. sort() 对list集合的元素进行升序排序Collections.sort(list);System.out.println(list);//输出结果为:[张三, 张麻子, 李四, 王五]} }运行结果如下:
补充第三种方法,如果对自定的对象进行排序的话,默认的 sort 是会报错的,所以得自定义比较,创建一个比较器。
代码如下:
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List;public class Text_Collections {public static void main(String[] args) {Student s1 = new Student("张三",19);Student s2 = new Student("李四",33);Student s3 = new Student("王五",21);List<Student> list = new ArrayList<>();Collections.addAll(list,s1,s2,s3);//自定义,根据年龄进行排序Collections.sort(list, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return o1.getAge()- o2.getAge();}});System.out.println(list);} }运行结果如下:
相关文章:
进阶JAVA篇- Collcetions 工具类与集合的并发修改异常问题
目录 1.0 集合的并发修改问题 1.1 如何解决集合的并发修改问题 2.0 Collcetions 工具类的说明 1.0 集合的并发修改问题 我们可以简单的认为,就是使用迭代器遍历集合时,又同时在删除集合中的数据,程序就会出现并发修改异常的错误。 代码如下&…...
npm WARN npm npm does not support Node.js v12.18.3
npm 不支持 Node.js v12.18.3 , npm和node的版本不匹配。 npm WARN npm npm does not support Node.js v12.18.3 npm WARN npm You should probably upgrade to a newer version of node as we npm WARN npm cant make any promises that npm will work with this v…...
转行做程序员,多晚都不晚
大家好啊,我是董董灿。 最近有不少小伙伴加我微信咨询一些问题,有同学想了解AI行业的现状,想着转行的,也有在校生想了解毕业后工作方向的,当然也有想学习编程知识的。 诚惶诚恐,没想到之前写的文章&#…...
自动化运维ansible
一、Ansible概述: 是一个配置管理系统(configuration management system),当下最流行的批量自动化运维工具之一。 Ansible是一个开源的自动化工具,用于配置管理、应用程序部署和编排等 IT 任务的执行。它专注于简单性和可扩展性,并…...
记录:Unity脚本的编写4.0
目录 前言导入音乐编写脚本 前言 之前使用脚本对uniry中的模型进行了控制,诸如使用键盘控制对象模型的移动或者使用鼠标对对象模型进行角度的切换(或者是类似的东西),而我们在游戏的过程中,总是伴随着一些好听的bgm&a…...
vue中引入jquery解决跨域问题
1、vue 工程文件 package.json 中 引入 “dependencies”: { “jquery”:“^2.2.4” }, 2、控制台执行命令,当前工程文件夹下 cnpm install 3、修改的vue文件中 加入 import $ from ‘jquery’ 4、调用 ajax请求 $.ajax({url:http://192.168.0.10:9099/strutsJspA…...
车规MCU开发工具之Vector DaVinci Configurator执行arxml合并操作
环境 Step1 导入要合并的arxml 、 Step 2 比较、合并过程 <完>...
数字滚动动效(纯HTML5版和Vue版本)
数字从0到指定数字的滚动动效,直接上代码; H5 <!DOCTYPE html> <html> <head><style>/* 设置数字显示的样式 */.counter {font-weight:700;font-size: 36px;color: #333;}</style> </head> <body><div cl…...
Leetcode—2530.执行K次操作后的最大分数【中等】(C语言向上取整数学公式)
2023每日刷题(五) Leetcode—2530.执行K次操作后的最大分数 向上取整思想 参考了这篇文章 有人肯定会问,这个向上取整为什么是这样来的。接下来我简单讲解一下。 数学式: x y 数学式:\frac{x}{y} 数学式:…...
CMakeList 编写示例
cmake_minimum_required(VERSION 3.8) #指定cmake的最小版本 set(PROJECT_NAME Untitled_1) #初始化变量 project(${PROJECT_NAME} VERSION 1.0) #创建一个project set(CMAKE_AUTOMOC ON) #初始化内置变量, 该变量为Qt工程专属变量 set(CMAKE_AUTORCC ON) set(CMAKE_A…...
OSI笔记
由7层组成,由下自上分别为: 物理层(硬件方面,例如物理网络设备、布线电缆、光纤等), 传输数据主要是比特流0 1 、电信号数据链路层(确定了0 1 的分组方式,通过广播的方式࿰…...
C++之前置声明
在C中,前置声明是一种声明类或函数的方式,但并不定义它们。 前置声明的主要目的是为了解决编译时的依赖性问题,提高编译效率,并允许更灵活的代码组织。 原理 C前置声明可以减少头文件依赖的原理在于,通过前置声明&am…...
用3D扫描生成合成数据
合成数据集(Synthetic Datasets)正在成为计算机视觉模型训练的标准部分。 虽然新工具使合成数据集变得更容易访问,但除了标准机器学习过程之外,许多工具还需要对 3D 建模有基本的了解。 最简单的捷径是从现实世界中获取现有对象并…...
pip安装依赖报错
执行命令时 pip install --upgrade pip 报错: pip : 无法将“pip”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。pip install --upgrade pip~~~ Category…...
规范的项目流程图怎么写
编写规范的项目流程图可以遵循以下步骤: 1.明确项目目标:首先,明确项目的目标以及需要实现的结果。这有助于确定项目的范围和要求。 2.识别项目任务:识别和列出所有的任务,这可以包括获得资源、实施动作、收集信息等…...
模型部署笔记--Pytorch-FX量化
目录 1--Pytorch-FX量化 2--校准模型 3--代码实例 3-1--主函数 3-2--prepare_dataloader函数 3-3--训练和测试函数 1--Pytorch-FX量化 Pytorch在torch.quantization.quantize_fx中提供了两个API,即prepare_fx和convert_fx。 prepare_fx的作用是准备量化&#…...
解决XXLJOB重复执行问题--Redis加锁+注解+AOP
基于Redis加锁注解AOP解决JOB重复执行问题 现象解决方案自定义注解定义AOP策略redis 加锁实践 现象 线上xxljob有时候会遇到同一个任务在调度的时候重复执行,如下图: 线上JOB服务运行了2个实例,有时候会重复调度到同一个实例,有…...
云安全(1)--初识容器逃逸之特权容器逃逸
文章目录 前言privileged,特权容器逃逸环境配置实际利用实际环境利用计划任务/var/spool/cron/crontabs/ 适用于ubuntu debain/var/spool/cron 适用于centos ld.so.preloadssh 前言 在10.15号的上海中华武数杯的渗透赛里做到了一个k8s的题目,这应该是我第一次在比赛…...
二阶系统时域响应
二阶系统微分方程 二阶系统传递函数 二阶系统单位阶跃响应 过阻尼系统 临界阻尼系统 欠阻尼系统 无阻尼系统 二阶系统阶跃响应仿真 在Matlab中进行仿真,设置不同阻尼比2、1、0.5和0,可以得到结论: 阻尼比越小,系统响应速度越快&…...
mstsc改端口为33389
windows 远程默认端口3389不太安全,改成33389防下小人 把下面的2个文本存在后缀.reg的文件,双击导入注册表,"PortNumber"dword:0000826d 这个就是33389对应的端口号的16进制值,要想自己改成其它的换下值即可 Windows …...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...
MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释
以Module Federation 插件详为例,Webpack.config.js它可能的配置和含义如下: 前言 Module Federation 的Webpack.config.js核心配置包括: name filename(定义应用标识) remotes(引用远程模块࿰…...
【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道
文/法律实务观察组 在债务重组领域,专业机构的核心价值不仅在于减轻债务数字,更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明,合法债务优化需同步实现三重平衡: 法律刚性(债…...
WebRTC调研
WebRTC是什么,为什么,如何使用 WebRTC有什么优势 WebRTC Architecture Amazon KVS WebRTC 其它厂商WebRTC 海康门禁WebRTC 海康门禁其他界面整理 威视通WebRTC 局域网 Google浏览器 Microsoft Edge 公网 RTSP RTMP NVR ONVIF SIP SRT WebRTC协…...
TCP/IP 网络编程 | 服务端 客户端的封装
设计模式 文章目录 设计模式一、socket.h 接口(interface)二、socket.cpp 实现(implementation)三、server.cpp 使用封装(main 函数)四、client.cpp 使用封装(main 函数)五、退出方法…...
如何做好一份技术文档?从规划到实践的完整指南
如何做好一份技术文档?从规划到实践的完整指南 🌟 嗨,我是IRpickstars! 🌌 总有一行代码,能点亮万千星辰。 🔍 在技术的宇宙中,我愿做永不停歇的探索者。 ✨ 用代码丈量世界&…...
接口 RESTful 中的超媒体:REST 架构的灵魂驱动
在 RESTful 架构中,** 超媒体(Hypermedia)** 是一个核心概念,它体现了 REST 的 “表述性状态转移(Representational State Transfer)” 的本质,也是区分 “真 RESTful API” 与 “伪 RESTful AP…...
构建Docker镜像的Dockerfile文件详解
文章目录 前言Dockerfile 案例docker build1. 基本构建2. 指定 Dockerfile 路径3. 设置构建时变量4. 不使用缓存5. 删除中间容器6. 拉取最新基础镜像7. 静默输出完整示例 docker runDockerFile 入门syntax指定构造器FROM基础镜像RUN命令注释COPY复制ENV设置环境变量EXPOSE暴露端…...







