阿里巴巴开发手册中有一条:

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----快速失败的更多相关文章

  1. 有关集合的foreach循环里的add/remove

    转自:Hollis(微信号:hollischuang) 在阿里巴巴Java开发手册中,有这样一条规定: 但是手册中并没有给出具体原因,本文就来深入分析一下该规定背后的思考. 1 .foreach循环 ...

  2. 为什么阿里巴巴禁止在 foreach 循环里进行元素的 remove/add 操作--java.util.ConcurrentModificationException

    摘要 foreach循环(Foreach loop)是计算机编程语言中的一种控制流程语句,通常用来循环遍历数组或集合中的元素. 在阿里巴巴Java开发手册中,有这样一条规定: 但是手册中并没有给出具体 ...

  3. 为什么禁止在 foreach 循环里进行元素的 remove/add 操作

    首先看下边一个例子,展示了正确的做法和错误的错发: 这是为什么呢,具体原因下面进行详细说明: 1.foreach循环(Foreach loop)是计算机编程语言中的一种控制流程语句,通常用来循环遍历数 ...

  4. foreach循环里不能remove/add元素的原理

    foreach循环 ​    foreach循环(Foreach loop)是计算机编程语言中的一种控制流程语句,通常用来循环遍历数组或集合中的元素.Java语言从JDK 1.5.0开始引入forea ...

  5. 不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator 方式,如果并发操作,需要对 Iterator 对象加锁

    不要在 foreach 循环里进行元素的 remove/add 操作.remove 元素请使用 Iterator 方式,如果并发操作,需要对 Iterator 对象加锁. 正例: Iterator&l ...

  6. 为什么阿里巴巴Java开发手册中强制要求不要在foreach循环里进行元素的remove和add操作?

    在阅读<阿里巴巴Java开发手册>时,发现有一条关于在 foreach 循环里进行元素的 remove/add 操作的规约,具体内容如下: 错误演示 我们首先在 IDEA 中编写一个在 f ...

  7. 关于java中ArrayList的快速失败机制的漏洞——使用迭代器循环时删除倒数第二个元素不会报错

    一.问题描述 话不多说,先上代码: public static void main(String[] args) throws InterruptedException { List<Strin ...

  8. 阿里规范学习总结-不要再foreach对元素进行add()/remove()操作,

    在foreach循环中,对元素进行 remove()/add() 操作需要使用Iterator ,如果运行在多线程环境下,需要对Iterator对象枷锁. public class ForeachTe ...

  9. Java SE之快速失败(Fast-Fail)与快速安全(Fast-Safe)的区别[集合与多线程/增强For](彻底详解)

    声明 特点:基于JDK源码进行分析. 研究费时费力,如需转载或摘要,请显著处注明出处,以尊重劳动研究成果:博客园 - https://www.cnblogs.com/johnnyzen/p/10547 ...

随机推荐

  1. android application类简单介绍(一)

    每次应用程序执行时.应用程序的application类保持实例化的状态. 通过扩展applicaiton类,能够完毕下面3项工作: 1.对android执行时广播的应用程序级事件如低低内做出响应. 2 ...

  2. 【Android】自己定义View、画家(画布)Canvas与画笔Paint的应用——绘图、涂鸦板app的实现

    利用一个简单的绘图app来说明安卓的图形处理类与自己定义View的应用. 例如以下图,有一个供用户自己随意绘图.涂鸦的app. 这里不做那么花俏了,仅提供黑白两色.但能够改变笔尖的粗细. 实质上这里的 ...

  3. [计算机-好软推荐]证件照制作的利器,不会PS也没有关系

    多年前发现了这一款软件,后来不管电脑是从xp升级到win7,还是从win7升级到win8,我都收藏了它. 我用它主要是制作大头照,然后通过咔嚓鱼冲印,比起一般的冲印店要便宜些. 这个软件是台湾的朋友开 ...

  4. ACdream 1412 DP+排列组合

    2-3 Trees Problem Description 2-3 tree is an elegant data structure invented by John Hopcroft. It is ...

  5. YTU 2542: 弟弟的作业

    2542: 弟弟的作业 时间限制: 1 Sec  内存限制: 128 MB 提交: 130  解决: 57 题目描述 你的弟弟刚做完了"100以内数的加减法"这部分的作业,请你帮他 ...

  6. YTU 2505: 啤酒和饮料

    2505: 啤酒和饮料 时间限制: 1 Sec  内存限制: 128 MB 提交: 850  解决: 318 题目描述 啤酒每罐2.3元,饮料每罐1.9元.小明买了若干啤酒和饮料,一共花了s元. 我们 ...

  7. POJ1743 Musical Theme 最长重复子串 利用后缀数组

    POJ1743 题目意思是求不重叠的最长相同变化的子串,输出该长度 比如1 2 3 4 5 6 7 8 9 10,最长长度为5,因为子串1 2 3 4 5 和 6 7 8 9 10变化都一样的 思路: ...

  8. 洛谷P1365 WJMZBMR打osu! / Easy——期望DP

    题目:https://www.luogu.org/problemnew/show/P1365 平方和怎样递推? 其实就是 (x+1)^2 = x^2 + 2*x + 1: 所以我们要关注这里的 x — ...

  9. bzoj1052覆盖问题(二分+贪心)

    1052: [HAOI2007]覆盖问题 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2446  Solved: 1131[Submit][Stat ...

  10. 【杂文】5亿大质数表(5e8)

    [杂文]\(5\) 亿大质数表(\(5e8\)) 在写哈希,刷数论题时曾一度想要查质数,\(F**k\) 百度文库数据又少,翻页蛋疼,还不给复制,真的是服了. 于是在我闲的蛋疼的时候就搞了个质数表出来 ...