做了3年的开发,不会循环删除 List 中的元素,心态崩了
真正的大师,永远怀着一颗学徒的心
【资料图】
最近和同事聊天,说他手下的一个开发,工作 3 年多了,一个需求的技术点,需要循环删除 List 中的元素,整了半天,说程序报错,不会弄。。
他挺无语的,和我倾诉,我说工作 3 年多也不至于吧,不会的话,在网上找找也能搞定啊,他说确实是的,这个开发挺难带的,简直崩溃!!
循环删除 List 中的元素,这个问题是有需要的注意点的,如果是个新手,确实会遇到一点麻烦,但工作 3 年多,我觉得应该不至于啊,好吧,这篇文章就来梳理一下这其中的道道。
1. List中删除元素
1.1 前言
注:不管在什么业务场景下,都不要都不要对List使用for循环的同时,删除List集合中的元素
在阿里巴巴开发手册也明确说明禁止使用foreach删除、增加List元素。
1.2 问题
下面举个实例场景,看一下为什么不能使用for循环
比如有如下的一个list:
public List<String> initList = Arrays.asList("a", "ab", "abc", "abcd", "bcd");
1.3 需求
在上面的initList集合中,元素类型为String,有5个元素,怎么删除这些元素中包含字符""a""的元素。
1.4 方法
1.4.1 普通 for 循环删除(不可靠)
@Testpublic void remove1() { List<String> list = new ArrayList(initList); for (int i = 0; i < list.size(); i++) { if (list.get(i).contains("a")) { list.remove(i); } } System.out.println(list);}
输出结果:[ab, abcd, bcd]
分析:
问题就出在 list.size(),因为 list.size() 和 i 都是动态变化的,索引为i的元素删除后,后边元素的索引自动向前补位,i 的值一直在累加,list.size() 一直在减少,所以 list 就会早早结束了循环。这种方式会导致只要每删除一个元素,就会漏掉下一个元素。
1.4.2 增强for循环删除(不可靠)
@Testpublic void remove1() { List<String> list = new ArrayList(initList); for (String str : list) { if (str.contains("a")) { list.remove(str); } } System.out.println(list);}
运行报错:
分析:
会导致Concurrent Modification Exception:并发修改异常
其实,for(xx in xx) 就是增强的 for循环,即迭代器 Iterator 的加强实现,其内部是调用的 Iterator 的方法,为什么会报ConcurrentModificationException 错误,我们来看下源码:
取下个元素的时候都会去判断要修改的数量(modCount)和期待修改的数量(expectedModCount)是否一致,不一致则会报错,而 ArrayList 中的 remove 方法并没有同步期待修改的数量(expectedModCount)值,所以会抛异常了。
1.4.3 普通 for 循环提取变量删除(抛异常)
把普通for循环例子的 size 提出变量,经行循环
@Testpublic void remove2() { List<String> list = new ArrayList(initList); int size = list.size(); for (int i = 0; i < size; i++) { String str = list.get(i); if (str.startsWith("a")) { list.remove(i); } } System.out.println(list);}
运行报错:
分析:
这里问题显而易见,因为 size 变量是固定的,但 list 的实际大小是不断减小的,而 i 的大小是不断累加的,一旦 i >= list 的实际大小肯定就异常了。
1.4.4 迭代器循环迭代器删除(可靠)
@Testpublic void remove4() { List<String> list = new ArrayList(initList); for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) { String str = iterator.next(); if (str.contains("a")) { iterator.remove(); } } System.out.println(list);}
输出结果:[bcd]
结果输出正常,所以,这种删除方法是安全的,推荐使用。
1.4.5 新特性stream进行List去重(可靠)
@Testpublic void remove2() { List<String> list = new ArrayList(initList); List<String> list1 = list.stream() .filter(f->!f.contains("a")) .collect(Collectors.toList()); System.out.println(list1);}
输出结果:[bcd]
结果输出正常,所以,这种删除方法是安全的,推荐使用,也是JAVA8的新特性。
1.5 结论
使用迭代器循环迭代器
使用java8新特性Strem流的方式
关键词:
推荐阅读
飞机发明者是谁?飞机有哪些类型?
飞机发明者是谁?飞机是由莱特兄弟发明的,莱特兄弟是美国著名的发明家,他们的哥哥是威尔伯菜特,他们的弟弟是奥维尔莱特。1903年12月17日 【详细】
Google I/O线上开发者大会发布 安卓12新特性支持什么功能?
现在大多数人用的手机还是安卓机,本次Android 12的发布自然也是引起了一大波的关注,国内不少厂商也参与了测试,我们来看看谷歌正式发布A 【详细】
航天员出舱七个小时怎么喝水?太空行走的危险和好处是什么?
航天员出舱七个小时怎么喝水?7月4日,中国宇航员刘伯明和汤洪波出航活动,整个进程持续了7个多小时。据报道,宇航员在舱外服里有饮水袋,在 【详细】
NASA毅力号录下了来自火星的声音 毅力号录下了来自火星的声音怎么回事?
NASA毅力号录下了来自火星的声音近日,有报道称,NASA毅力号录下了来自火星的声音,这非常的奇妙,相信大家十分的感兴趣,下面一起去看看吧 【详细】
北京上空现三个太阳 古代幻日现象预兆什么?
北京上空现三个太阳北京上空现三个太阳 专家释疑今日登上热搜,主要是在12月29日有网友拍到北京上空出现了三个太阳。对于这一现象气象专家 【详细】
相关新闻
- 做了3年的开发,不会循环删除 List 中的元素,心态崩了
- 每日看点!比特币核心开发者提出新型修剪节点
- 全网吐槽的骁龙888迎来第二春,小米11更新MIUI 14,宛如换台新机
- 特斯拉为什么疯狂降价?听了马斯克的回答,崇敬之情油然而生
- 区块链技术的发展与应用:探索数字世界的新篇章 全球快播
- 怎么解散群并彻底删除消息_怎么解散群 天天速看
- 夏婉安(夏婉安现在多少岁了)
- 苦涩的反义词(苦涩的反义词)
- 2022年度中国科学十大进展发布
- aigc颠覆玩起来如何?怎么样AI模拟真人情感配音
- 英国政府宣布禁止在官方手机上使用TikTok,引发安全疑虑 当前看点
- 滚动:2022中国手机安全状况报告:虚假兼职成主要诈骗形式
- 如人饮水冷暖自知什么意思(如人饮水,冷暖自知什么意思)-全球热头条
- 今日热门!惊声尖笑1(惊声尖笑1的结局到底是什么意思)
- 全球资讯:OPPOk10跟真我Q5Pro哪款手机性价比更高?更值得入手?
- 苹果macOS默许被“黑”,恰如盗版微软Windows的睁一只眼闭一只眼|世界速讯
- 精选!未来,实体店能不能反超“电商与直播”?
- 一条横屏中视频,抖音800万播放量,今日头条43万播放量,多少钱
- 云呼叫系统这些功能助力企业做营销
- 动态:盗钥匙的方法