禁止foreach循环使用remove/add----快速失败
阿里巴巴开发手册中有一条:
7【强制】不要在 foreach 循环里进行元素的 remove / add 操作。 remove 元素请使用 Iterator
方式,如果并发操作,需要对 Iterator 对象加锁。
正例:
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if (删除元素的条件) {
iterator.remove();
}
}
反例:
List<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
for (String item : list) {
if ("1".equals(item)) {
list.remove(item);
}
}
说明:以上代码的执行结果肯定会出乎大家的意料,那么试一下把“1”换成“2”,会是同样的
结果吗?
代码重现:
public static void main(String[] args) {
List<String> list = Lists.newArrayList("a","b","c","d");
for (String userName : list) {
if (userName.equals("a")) {
list.remove(userName);
list.add(userName);
}
}
}
结果:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at com.it.test.TestUnit.main(TestUnit.java:23)
异常:
/*
*modCount:实际修改次数
*expectedModCount:期望修改次数
*/
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
这个就是就是快速失败机制——fail-fast 原因: 出现这个异常的原因,是因为foreach循环中,通过iterator修改了集合,但是元素的add/remove却是直接使用的集合类自己的方法。通过反编译得知,foreach通过while和Iterator实现的。 这就导致iterator在遍历的时候,会发现有一个元素在自己不知不觉的情况下就被删除/添加了,就会抛出一个异常,用来提示用户,可能发生了并发修改。
解决:
1、使用普通for循环进行操作,因为普通for循环并没有用到Iterator的遍历,所以压根就没有进行fail-fast的检验。
2、直接使用Iterator进行操作
3、使用Java 8中提供的filter过滤
4、直接使用fail-safe的集合类
5、使用增强for循环其实也可以
以上这五种方式都可以避免触发fail-fast机制,避免抛出异常。如果是并发场景,建议使用concurrent包中的容器,如果是单线程场景,Java8之前的代码中,
建议使用Iterator进行元素删除,Java8及更新的版本中,可以考虑使用Stream及filter。
原文地址:https://mp.weixin.qq.com/s/e9ITxUmsMFhfjeHhOgTtfA
禁止foreach循环使用remove/add----快速失败的更多相关文章
- 有关集合的foreach循环里的add/remove
转自:Hollis(微信号:hollischuang) 在阿里巴巴Java开发手册中,有这样一条规定: 但是手册中并没有给出具体原因,本文就来深入分析一下该规定背后的思考. 1 .foreach循环 ...
- 为什么阿里巴巴禁止在 foreach 循环里进行元素的 remove/add 操作--java.util.ConcurrentModificationException
摘要 foreach循环(Foreach loop)是计算机编程语言中的一种控制流程语句,通常用来循环遍历数组或集合中的元素. 在阿里巴巴Java开发手册中,有这样一条规定: 但是手册中并没有给出具体 ...
- 为什么禁止在 foreach 循环里进行元素的 remove/add 操作
首先看下边一个例子,展示了正确的做法和错误的错发: 这是为什么呢,具体原因下面进行详细说明: 1.foreach循环(Foreach loop)是计算机编程语言中的一种控制流程语句,通常用来循环遍历数 ...
- foreach循环里不能remove/add元素的原理
foreach循环 foreach循环(Foreach loop)是计算机编程语言中的一种控制流程语句,通常用来循环遍历数组或集合中的元素.Java语言从JDK 1.5.0开始引入forea ...
- 不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator 方式,如果并发操作,需要对 Iterator 对象加锁
不要在 foreach 循环里进行元素的 remove/add 操作.remove 元素请使用 Iterator 方式,如果并发操作,需要对 Iterator 对象加锁. 正例: Iterator&l ...
- 为什么阿里巴巴Java开发手册中强制要求不要在foreach循环里进行元素的remove和add操作?
在阅读<阿里巴巴Java开发手册>时,发现有一条关于在 foreach 循环里进行元素的 remove/add 操作的规约,具体内容如下: 错误演示 我们首先在 IDEA 中编写一个在 f ...
- 关于java中ArrayList的快速失败机制的漏洞——使用迭代器循环时删除倒数第二个元素不会报错
一.问题描述 话不多说,先上代码: public static void main(String[] args) throws InterruptedException { List<Strin ...
- 阿里规范学习总结-不要再foreach对元素进行add()/remove()操作,
在foreach循环中,对元素进行 remove()/add() 操作需要使用Iterator ,如果运行在多线程环境下,需要对Iterator对象枷锁. public class ForeachTe ...
- Java SE之快速失败(Fast-Fail)与快速安全(Fast-Safe)的区别[集合与多线程/增强For](彻底详解)
声明 特点:基于JDK源码进行分析. 研究费时费力,如需转载或摘要,请显著处注明出处,以尊重劳动研究成果:博客园 - https://www.cnblogs.com/johnnyzen/p/10547 ...
随机推荐
- ExtAspNet从DataTable里导出Excel
protected void btn_ToExcel_Click(object sender, EventArgs e) { Response.ClearContent(); Response.Add ...
- c#实现播放器的集中方式
http://www.cnblogs.com/iskyoole/archive/2012/03/25/2417181.html(原文链接地址) 一.使用vs自带的windows media play控 ...
- Bootstrap Dropdown 源码分析
/* ======================================================================== * Bootstrap: dropdown.js ...
- centos ifconfig 无法使用问题
centos ifconfig 无法使用问题 # ifconfig bash: ifconfig: command not found # yum search ifconfig Loaded plu ...
- USACO Section1.1PROB Broken Necklace
有点麻烦的一道模拟(官方题解好像有复杂度为$O(n)$DP的姿势?,感觉好烦,以后再细看~ 在一些细节上调试了很久很久,囧RZ /* ID: jusonal1 PROG: beads LANG: C+ ...
- IDEA 单元测试
下载所需的两个 jar 包,下载地址:Download and Install · junit-team/junit4 Wiki · GitHub junit-4.12.jar hamcrest-co ...
- openssh常用命令记录
command description date ssh [user@]hostname[:port] 登录远程机器 2017-03-21 scp <local_file> <use ...
- js的多种数值分类相加,数据先后没有顺序,不确定同类数据多少
下面是js源码片段.看的是思想. <script type="text/javascript"> deg_countMyChart = function(deptcod ...
- c++编程中处理char和wchar_t的好工具
/* ttype.h sdragonx 2015-02-18 18:32:43 这个几个模版函数是为了处理ansi或unicode,使字符串值或者字符串函数能够在模版中使用 2018/7/26 23: ...
- 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 The Heaviest Non-decreasing Subsequence Problem
Let SS be a sequence of integers s_{1}s1, s_{2}s2, ......, s_{n}snEach integer is is associ ...