不要在foreach循环里进行元素的remove/add操作

不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator 方式。

反例:

public class ForeachTest {
    private List<String> list = new ArrayList<String>();

    @Test
    public void forTest() {
        list.add("1");
        list.add("2");
        for(String temp : list) {
            if("1".equals(temp)) {
                list.remove(temp);
            }
        }
        for(String temp : list) {
            System.out.println(temp + " ");
        }
    }
}

结果

如果将1换成2,结果就出错了

产生Concurrent Modification Exception原因是:当list.remove(Object o)方法之后,modCount和expectedModCount不相等了,然后当代码执行到next()方法时,判断了checkForComodification(),发现两个数值不等,就抛出该Exception;add(Object o)方法也是一样原因;

另外,Iterator是工作在一个独立的线程中,并且拥有一个mutex锁, Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的list对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。 所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。

但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。

正例:

public class ForeachTest {
    private List<String> list = new ArrayList<String>();

    @Test
    public void forTest2() {
        list.add("1");
        list.add("2");
        Iterator<String> it = list.iterator();
        while(it.hasNext()) {
            String temp = it.next();
            if("2".equals(temp)) {
                it.remove();
            }
        }
        for(String temp : list) {
            System.out.println(temp + " ");
        }
    }
}

结果很完美,

如果并发操作,需要对 Iterator 对象加锁。

原文地址:https://www.cnblogs.com/hongzm/p/8483073.html

时间: 2024-08-04 06:22:12

不要在foreach循环里进行元素的remove/add操作的相关文章

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

在阿里巴巴Java开发手册中,有这样一条规定:但是手册中并没有给出具体原因,本文就来深入分析一下该规定背后的思考.1.foreach循环foreach循环(Foreach loop)是计算机编程语言中的一种控制流程语句,通常用来循环遍历数组或集合中的元素.Java语言从JDK 1.5.0开始引入foreach循环.在遍历数组.集合方面,foreach为开发人员提供了极大的方便.通常也被称之为增强for循环.foreach 语法格式如下: for(元素类型t 元素变量x : 遍历对象obj){ 引

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

这个问题我在实际写代码中也遇到过,当时还很疑惑,刚看到这里有一些解释得挺清楚,记录一下: 原文地址为:https://mp.weixin.qq.com/s?__biz=MzI3NzE0NjcwMg==&mid=2650123395&idx=1&sn=b089eac4f561f58ee8a92602db17f577&chksm=f36bb1a2c41c38b4f36c1a84f205e188a6a8aa2684f316e4dcb8d1162b6e94b970c670b2e5b

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

在阅读<阿里巴巴Java开发手册>时,发现有一条关于在 foreach 循环里进行元素的 remove/add 操作的规约,具体内容如下: 错误演示 我们首先在 IDEA 中编写一个在 foreach 循环里进行 remove 操作的代码: import java.util.ArrayList; import java.util.List; public class ForEachTest { public static void main(String[] args) { List<S

为什么在foreach循环中不要对元素进行remove/add操作?

目录 前言 正文 为什么结果如此不同? remove/add方法? 如何解决? 前言 在阿里巴巴Java开发手册中,有下面这样的规定: 这篇文章我们就来深入探讨其中的原因. 正文 为什么结果如此不同? 我们先来看看前言中的反例会出现什么意料之外的结果: ---------------------------------------------------------------------------------------------------------------------------

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

foreach循环 ? ?? foreach循环(Foreach loop)是计算机编程语言中的一种控制流程语句,通常用来循环遍历数组或集合中的元素.Java语言从JDK 1.5.0开始引入foreach循环.在遍历数组.集合方面,foreach为开发人员提供了极大的方便.通常也被称之为增强for循环. ? ?? 在日常开发中,foreach循环用的非常多,但是有一点要非常小心,就是不能在这个循环里对数组或者集合里的元素进行remove或者add操作,否则会抛出java.util.Concurr

将数组里相同元素提取出来

将数组Arr里相同的元素提取出来放在一个小数组里,再将小数组放在一个大数组dataArry里 NSMutableArray *Arr =[NSMutableArray arrayWithObjects:@"1",@"2",@"1",@"3",@"2",@"2",@"4",@"1",@"2",@"2",@&qu

再学Java 之 foreach循环

从Java 5 之后,Java提供了一种新的循环:foreach循环,这种循环遍历数组和集合更加简洁. foreach循环语法格式如下: for ( type variableName : array | collection){ //variableName自动迭代访问每个元素 } 在很多书籍中,都能找到这么一句话"使用foreach循环迭代数组元素时,并不能改变数组元素".如: String books = {"a","b","c&

java容器中遍历循环Iterator 和 Foreach 循环

最近遇到这样一个问题,要删除一个集合中的某个元素,该怎么解决? 我自己写了两段代码来删除,都报了一个错java.util.ConcurrentModificationException:为了让更多可能没注意到这个点的程序猿注意一下,我在这里分享下~ 先看代码 1 package com.zwt1234; 2 3 import java.util.HashSet; 4 import java.util.Iterator; 5 import java.util.Set; 6 7 public cla

集合中的 for-Each循环

 数组的加强型的for-Each循环很简单,我们再来看一下集合中的for-Each 循环又是怎么样的.我们都知道集合中的遍历都是通过迭代(iterator)完成的.也许有人说,也可以按照下面的方式来遍历集合,不一定非要使用迭代: 1 List<String> list = new LinkedList<String>(); 2 list.add("a"); 3 list.add("b"); 4 list.add("c");