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

任何时候都不要在 for 循环中删除 List 集合元素!!!

首先说结论:无论什么场景,都不要对List使用for循环的同时,删除List集合元素,因为这么做就是不对的。

阿里开发手册也明确说明禁止使用foreach删除、增加List元素。
正确删除元素的方式是使用迭代器(Iterator),代码如下:

List<String> list = new ArrayList<>();
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {// 删除元素iterator.remove();
}

JDK8后lambda写法:

list.removeIf(s -> s.contains("a"));

不想知道为什么不能使用for循环删除List集合元素的,看完前言就可以关闭本页面了,想知道原因的继续往下看

下面举个实例场景,看一下为什么不能使用for循环。

需求
一个List集合,元素类型为String,有N个元素,删除这些元素中包含字符’‘a’'的元素。

假设集合内容如下:

List<String> list = new ArrayList<>(4);
list.add("a");
list.add("ab");
list.add("abc");
list.add("abcd");
public static void main(String[] args) {List<String> list = new ArrayList<>(4);list.add("a");list.add("ab");list.add("abc");list.add("abcd");Iterator<String> iterator = list.iterator();while (iterator.hasNext()) {if (iterator.next().contains("a")) {// 删除元素iterator.remove();}}System.out.println(list);
}

输出结果为

[]

错误答案1:普通for循环(for-i)

public static void main(String[] args) {List<String> list = new ArrayList<>(4);list.add("a");list.add("ab");list.add("abc");list.add("abcd");for (int i = 0; i < list.size(); i++) {if (list.get(i).contains("a")) {list.remove(i);}}System.out.println(list);
}

输出结果为

[ab, abcd]

分析
普通for循环遍历List集合的同时,删除List中的元素是可以运行的代码,但在大多数场景下,不能使用这种方式,上边的结果也印证了这一点,虽然你的代码不会报错,运行也正常,但在本实例中,这么写就是BUG。

BUG原因:索引为i的元素删除后,后边元素的索引自动向前补位,即原来索引为i+1的元素,变为了索引为i的元素,但是下一次循环取的索引是i+1,此时你以为取到的是原来索引为i+1的元素,其实取到是原来索引为i+2的元素。

只要每删除一个元素,就会漏掉下一个元素,所以这种方式从逻辑上来说是存在bug的,无论什么需求场景,都不建议用这种方式,因为不可控因素太多(鬼知道生产环境中他会删掉多少元素,同时漏掉多少元素)。

既然这么写不报错,那么个别特殊场景确实可以使用这种普通for循环删除元素的,比如我们把实例的需求变动一下,改为:一个List集合,元素类型为String,有N个元素,删除这些元素中包含字符’a’的元素,如果有连续两个或以上元素包含’a’,那么只删除当前连续元素中的奇数位元素。虽然这种场景适用,但仍然不推荐,还是因为太不可控。

错误答案2:增强for循环(foreach)

public static void main(String[] args) {List<String> list = new ArrayList<>(4);list.add("a");list.add("ab");list.add("abc");list.add("abcd");for (String str : list) {if (str.contains("a")) {list.remove(str);}}System.out.println(list);
}

运行报错:

Exception in thread "main" java.util.ConcurrentModificationExceptionat java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)at java.util.ArrayList$Itr.next(ArrayList.java:859)at top.oldmoon.learn.test.ListTest.main(ListTest.java:24)

使用百度翻译可以知道:Concurrent Modification Exception:并发修改异常

分析

可以简单的理解为:foreach就不支持对集合中的元素进行增删操作,但是可以修改。

相关文章:

任何时候都不要在 for 循环中删除 List 集合元素!!!

首先说结论&#xff1a;无论什么场景&#xff0c;都不要对List使用for循环的同时&#xff0c;删除List集合元素&#xff0c;因为这么做就是不对的。 阿里开发手册也明确说明禁止使用foreach删除、增加List元素。 正确删除元素的方式是使用迭代器&#xff08;Iterator&#xff…...

koa+Vite+vue3+ts+pinia构建项目

一、 初始化构建项目 npm create vite myProject -- --template vue-ts 注&#xff1a;Vite 需要 Node.js 版本 14.18&#xff0c;16。然而&#xff0c;有些模板需要依赖更高的 Node 版本才能正常运行&#xff0c;当你的包管理器发出警告时&#xff0c;请注意升级你的 Node 版…...

k8s-yaml文件

文章目录一、K8S支持的文件格式1、yaml和json的主要区别2、YAML语言格式二、YAML1、查看 API 资源版本标签2、编写资源配置清单2.1 编写 nginx-test.yaml 资源配置清单2.2 创建资源对象2.3 查看创建的pod资源3、创建service服务对外提供访问并测试3.1 编写nginx-svc-test.yaml文…...

存储引擎

目录 ❤ MySQL存储引擎 什么是存储引擎? MySQL支持哪个存储引擎? ❤ 各种存储引擎的特性 概述 各种存储引擎的特性 各种搜索引擎介绍 ❤ 常用存储引擎及适用场景 ❤ 存储引擎在mysql中的使用 存储引擎相关sql语句 指定存储引擎建表 在建表时指定 在配置文件中…...

Go中 channel的使用

文章目录背景channel 简介使用说明声明发送和接受数据关闭channel使用示例背景 使用 sync 包和 context 包的工具可以实现多个协程之间互相协作, 但是没有一种很好的方式解决多个协程之间通信的问题. golang 作者 Rob Pike 说过一句话&#xff0c;不要通过共享内存来通信&…...

【C++】string OJ练习

文章目录1. 仅仅反转字母思路分析代码实现2. 字符串中的第一个唯一字符题目分析代码实现3. 《剑指offer》——替换空格解法一&#xff1a;寻找替换思路分析代码实现优化解法二&#xff1a;空间换时间思路分析代码实现4.字符串最后一个单词的长度思路分析代码实现5. 字符串相加思…...

进程间通信IPC

进程间通信IPC (InterProcess Communication) 一、进程间通信的概念 每个进程各自有不同的用户地址空间&#xff0c;任何一个进程的全局变量在另一个进程中都看不到&#xff0c;所以进程之间要交换数据必须通过内核&#xff0c;在内核中开辟一块缓冲区&#xff0c;进程1把数据…...

操作系统-页面淘汰算法(下)-软件设计(二十六)

操作系统-PV操作&#xff08;上&#xff09;-软件设计&#xff08;二十五&#xff09;https://blog.csdn.net/ke1ying/article/details/129476031 存储管理-分区存储组织 问&#xff1a;计算机系统内存大小为128k&#xff0c;当前系统分配情况如图&#xff0c;那么作业4再次申…...

23种设计模式-责任链模式(Android开发实际应用场景介绍)

什么是责任链模式 责任链模式是一种行为型设计模式&#xff0c;它的核心思想是将请求从一系列处理者中传递&#xff0c;直到其中一个处理者能够处理它为止。在这个过程中&#xff0c;请求可以被任何一个处理者处理&#xff0c;也可以被拒绝&#xff0c;直到有一个处理者能够处…...

Socket+Select+Epoll笔记

讲到epoll&#xff0c;就必须了解Socket&#xff0c;上篇博客写了Socket的基本使用方法&#xff0c;步骤主要为创建一个socketsocket是进程之间通信的&#xff0c;那么进程通信如何找到这个socket呢&#xff1f;当然是端口号&#xff0c;所以socket就要和端口号进行绑定&#x…...

git查看最近修改的文件

git log --name-status 每次修改的文件列表, 显示状态 git log --name-only 每次修改的文件列表 git log --stat 每次修改的文件列表, 及文件修改的统计 git whatchanged 每次修改的文件列表 git whatchanged --stat 每次修改的文件列表, 及文件修改的统计 git show 显示最…...

【算法基础(四)】堆排序(二)

堆排序&#xff08;二&#xff09; 把数组从零开始连续的一段 完全二叉树 size i 左 son 2*11 i 右 son 2*12 父 (i-1) / 2 堆是完全二叉树&#xff0c;分为大根堆和小根堆 在完全二叉树里&#xff0c;每一棵子数最大的值是头节点的值&#xff0c;就是大根堆 同理&…...

C++类型转换

C语言的转换是在变量前加类型名进行转换的&#xff0c;比如double pi 3.14;int a (int) pi;对于指针也是如此double* dptr &pi;int* iptr (int*)dptr;虽然c兼容了C语言的转型方式&#xff0c;但是也做了很多限制&#xff0c;比如向上类型转换&#xff0c;在c中建议使用…...

Keil MDK6要来了,将嵌入式软件开发水平带到新高度,支持跨平台(2023-03-11)

注&#xff1a;这个是MDK6&#xff0c;不是MDK5 AC6&#xff0c;属于下一代MDK视频版&#xff1a; https://www.bilibili.com/video/BV16s4y157WF Keil MDK6要来了&#xff0c;将嵌入式软件开发水平带到新高度&#xff0c;支持跨平台一年一度的全球顶级嵌入式会展Embedded Wor…...

蓝桥杯刷题第九天

题目描述本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。素数就是不能再进行等分的整数。比如7&#xff0c;11。而 9 不是素数&#xff0c;因为它可以平分为 3 等份。一般认为最小的素数是2&#xff0c;接着是 3&#xff0c;5&…...

a-tree-select 基本使用,下拉框高度和宽度设置、回显时滚动条定位解决。

目录一、基本使用1. 界面效果2. 代码实现3. 问题1&#xff1a;下拉框占满整个屏幕4. 问题4&#xff1a;菜单内容过长时&#xff0c;下拉菜单宽度无限变宽。二、数据回显、滚动条定位1. 界面效果2. 代码实现2.1 获取默认展开节点2.1.1 代码实现2.1.2 说明2.2 设置滚动条定位2.2.…...

【Linux】之nc命令(连接与扫描指定端口、监测服务端口的使用情况)解析、详解实例、邮件告警

&#x1f341;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; 文章目录nc命令简介nc命令的安装nc命令语法格式…...

cdn简单配置

cdn配置域名接入CDN编辑CDN配置本地修改hosts文件&#xff0c;绕过公网解析域名接入CDN 添加CDN域名以及回源配置 编辑CDN配置 默认后端端口是80&#xff0c;如果测试发现无法访问&#xff0c;则可能是443或其它 如果域名在CDN后端有https强制跳转&#xff0c;后端端口一定是44…...

前端安全(自留)

目录XSS——跨站脚本常见解决CSRF ——跨站请求伪造常见解决XSS——跨站脚本 当目标站点在渲染html的过程中&#xff0c;遇到陌生的脚本指令执行。 攻击者通过在网站注入恶意脚本&#xff0c;使之在用户的浏览器上运行&#xff0c;从而盗取用户的信息如 cookie 等。 常见 解…...

零基础转行云计算可行吗

目前处于云年代&#xff0c;云计算运维工程师的工作远景还是十分广泛的。像是阿里云计算&#xff0c;滴滴&#xff0c;抖音等等互联网大厂目前都在使用云核算技能。 云计算运维工程师的薪资水平也十分可观。 运维工程师(Operations)&#xff0c;在国内又称为运维开发工程师(Dev…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数&#xff0c;对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

通过Wrangler CLI在worker中创建数据库和表

官方使用文档&#xff1a;Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后&#xff0c;会在本地和远程创建数据库&#xff1a; npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库&#xff1a; 现在&#xff0c;您的Cloudfla…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

2024年赣州旅游投资集团社会招聘笔试真

2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

站群服务器的应用场景都有哪些?

站群服务器主要是为了多个网站的托管和管理所设计的&#xff0c;可以通过集中管理和高效资源的分配&#xff0c;来支持多个独立的网站同时运行&#xff0c;让每一个网站都可以分配到独立的IP地址&#xff0c;避免出现IP关联的风险&#xff0c;用户还可以通过控制面板进行管理功…...

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务&#xff0c;但是又不想花钱&#xff0c;所以就想着自己搭建一个&#xff0c;刚好我们用的一个开源框架已经集成了MinIO&#xff0c;所以就选了这个 我这边对文件服务性能要求不是太高&#xff0c;单机版就可以 安装非常简单&#xff0c;几个命令就…...