当前位置:首页 > 科技  > 软件

五年程序员使用ArrayList居然用forEach遍历删除元素?

来源: 责编: 时间:2024-01-08 09:16:58 345观看
导读哈喽,大家好,我是了不起。通常1-3年工作经验的程序员算是初级程序员,再往后基本上就是在编程领域有了一定经验的高级程序员了。但是最近公司代码review时,我居然发现一个 5 年工作经验的程序员,使用 ArrayList 居然用 forE

哈喽,大家好,我是了不起。YNx28资讯网——每日最新资讯28at.com

通常1-3年工作经验的程序员算是初级程序员,再往后基本上就是在编程领域有了一定经验的高级程序员了。YNx28资讯网——每日最新资讯28at.com

但是最近公司代码review时,我居然发现一个 5 年工作经验的程序员,使用 ArrayList 居然用 forEach 遍历删除元素?YNx28资讯网——每日最新资讯28at.com

1、现场还原

由于公司代码有一定敏感,我这里把代码进行脱敏,大家一起来看看:YNx28资讯网——每日最新资讯28at.com

public static void main(String[] args) {    ArrayList<String> list = new ArrayList<>(Arrays.asList("1", "2", "3"));    list.forEach(item -> {        if (item.startsWith("1")) {            list.remove(item);        }    });}

乍看之下,这段代码似乎没什么问题。但实际运行时,它会抛出ConcurrentModificationException异常。YNx28资讯网——每日最新资讯28at.com

这是为什么呢?我们运行这段代码,报错如下 :YNx28资讯网——每日最新资讯28at.com

图片图片YNx28资讯网——每日最新资讯28at.com

2、原因分析

其实 forEach 是一个语法糖,我们编译后的代码如下:YNx28资讯网——每日最新资讯28at.com

//这是一颗语法糖,编译后相当于:for(Iterator i = lists.iterator();i.hasNext();){    String s = (String)i.next();    if(s.startsWith("1")){        list.remove(s);    }}

然后这里的 i.next() 方法:YNx28资讯网——每日最新资讯28at.com

public E next() {    checkForComodification();    int i = cursor;    if (i >= size)        throw new NoSuchElementException();    Object[] elementData = ArrayList.this.elementData;    if (i >= elementData.length)        throw new ConcurrentModificationException();    cursor = i + 1;    return (E) elementData[lastRet = i];}final void checkForComodification() {    if (modCount != expectedModCount)       throw new ConcurrentModificationException();}

这样就很明了了,在Java中,当我们试图在遍历一个集合的同时修改它时,就会遇到ConcurrentModificationException。这是因为ArrayList的迭代器设计为快速失败(fail-fast),即在检测到集合在迭代期间被修改时立即抛出异常。YNx28资讯网——每日最新资讯28at.com

3、如何正确删除?

3.1 使用迭代器的remove方法

Iterator<String> iterator = list.iterator();while (iterator.hasNext()) {    String item = iterator.next();    if (item.startsWith("1")) {        iterator.remove();    }}

这种方法可以保证在删除元素的同时不会破坏迭代器的状态。YNx28资讯网——每日最新资讯28at.com

3.2 使用removeIf方法

从Java 8开始,ArrayList引入了removeIf方法,这是删除元素的另一种便捷方式:YNx28资讯网——每日最新资讯28at.com

list.removeIf(item -> item.startsWith("1"));

3.3 收集需要删除的元素

最后一种方法是首先收集所有需要删除的元素,然后再进行删除:YNx28资讯网——每日最新资讯28at.com

List<String> itemsToRemove = list.stream()    .filter(item -> item.startsWith("1"))    .collect(Collectors.toList());list.removeAll(itemsToRemove);

本文链接:http://www.28at.com/showinfo-26-57900-0.html五年程序员使用ArrayList居然用forEach遍历删除元素?

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 推荐一个13k的微服务编排引擎Netflix Conductor

下一篇: 20 个让用户惊叹不已的按钮效果

标签:
  • 热门焦点
  • 鸿蒙OS 4.0公测机型公布:甚至连nova6都支持

    华为全新的HarmonyOS 4.0操作系统将于今天下午正式登场,官方在发布会之前也已经正式给出了可升级的机型产品,这意味着这些机型会率先支持升级享用。这次的HarmonyOS 4.0支持
  • 卢伟冰长文解析K60至尊版 对Redmi有着里程碑式的意义

    在今天的Redmi后性能时代战略发布会结束之后,Redmi总经理卢伟冰又带来了一篇长文,详解了为什么 Redmi 要开启后性能时代?为什么选择和 MediaTek、Pixelworks 深度合作?以及后性
  • 线程通讯的三种方法!通俗易懂

    线程通信是指多个线程之间通过某种机制进行协调和交互,例如,线程等待和通知机制就是线程通讯的主要手段之一。 在 Java 中,线程等待和通知的实现手段有以下几种方式:Object 类下
  • 19个 JavaScript 单行代码技巧,让你看起来像个专业人士

    今天这篇文章跟大家分享18个JS单行代码,你只需花几分钟时间,即可帮助您了解一些您可能不知道的 JS 知识,如果您已经知道了,就当作复习一下,古人云,温故而知新嘛。现在,我们就开始今
  • 使用LLM插件从命令行访问Llama 2

    最近的一个大新闻是Meta AI推出了新的开源授权的大型语言模型Llama 2。这是一项非常重要的进展:Llama 2可免费用于研究和商业用途。(几小时前,swyy发现它已从LLaMA 2更名为Lla
  • 使用AIGC工具提升安全工作效率

    在日常工作中,安全人员可能会涉及各种各样的安全任务,包括但不限于:开发某些安全工具的插件,满足自己特定的安全需求;自定义github搜索工具,快速查找所需的安全资料、漏洞poc、exp
  • 2023年,我眼中的字节跳动

    此时此刻(2023年7月),字节跳动从未上市,也从未公布过任何官方的上市计划;但是这并不妨碍它成为中国最受关注的互联网公司之一。从2016-17年的抖音强势崛起,到2018年的&ldquo;头腾
  • 信通院:小米、华为等11家应用商店基本完成APP签名及验签工作

    中国信通院表示,目前,小米、华为、OPPO、vivo、360手机助手、百度手机助手、应用宝、豌豆荚和努比亚等9家应用商店,以及抖音和快手2家新型应用分发平
  • OPPO K11样张首曝:千元机影像“卷”得真不错!

    一直以来,OPPO K系列机型都保持着较为均衡的产品体验,历来都是2K价位的明星机型,去年推出的OPPO K10和OPPO K10 Pro两款机型凭借各自的出色配置,堪称有
Top