不要在 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 对象加锁。

迭代(遍历)时候不可以使用集合的remove和add方法,但可使用Java迭代器的remove和add方法的更多相关文章

  1. JAVA集合迭代遍历和特性介绍

    数组.集合:都是一种容器,用一个对象管理多个对象:数组不能自动增长:只能存放同类型的元素 集合能自动扩容:部分集合允许存放不同类型的元素: 1.List: 有顺序的,允许存放重复的元素: 遍历:for ...

  2. java 数据类型:集合接口Collection之常用ArrayList;lambda表达式遍历;iterator遍历;forEachRemaining遍历;增强for遍历;removeIf批量操作集合元素(Predicate);

    java.util.Collection接口 Java的集合主要由两个接口派生出来,一个是Collection一个是Map,本章只记录Collection常用集合 集合只能存储引用类型数据,不能存储基 ...

  3. 重学 Java 设计模式:实战迭代器模式「模拟公司组织架构树结构关系,深度迭代遍历人员信息输出场景」

    作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 相信相信的力量! 从懵懂的少年,到拿起键盘,可以写一个Hell ...

  4. C#遍历可变化的集合

    如果用foreach,会造成被遍历的集合更改后带来异常问题. 方法一:用for循环可有效的解决这个问题. ;i<List.Count;i++) { if(条件是真) { List.Remove( ...

  5. c#迭代遍历带数组的json格式数据

    [1]首先我们先创建一个带数组形式的json格式的数组 1)我们按照结构定义一个类,如下: using System;using System.Collections.Generic;using Sy ...

  6. 【Java】遍历List/Set/Map集合的一些常用方法

    /* * 遍历List/Set/Map集合的一些常用方法 */import java.util.ArrayList;import java.util.HashMap;import java.util. ...

  7. 疑问:Iterator 遍历器和数据集合各种遍历方法的区别

    https://es6.ruanyifeng.com/#docs/iterator Iterator(遍历器)的概念 Iterator 接口主要供for...of消费 Iterator 的遍历过程是: ...

  8. Map集合的遍历方式以及TreeMap集合保存自定义对象实现比较的Comparable和Comparator两种方式

    Map集合的特点 1.Map集合中保存的都是键值对,键和值是一一对应的 2.一个映射不能包含重复的值 3.每个键最多只能映射到一个值上 Map接口和Collection接口的不同 Map是双列集合的根 ...

  9. YII框架中可以使用foreach遍历对象以及可以使用数组形式直接访问对象的原因

    YII框架中可以使用foreach遍历对象以及可以使用数组形式直接访问对象的原因在YII框架的使用过程中,我们可以使用foreach直接遍历findAll等方法返回的对象的属性为什么呢?其实这与CMo ...

随机推荐

  1. nginx上通过ssl证书将http转发为https

    环境:阿里云linux,ngnix 1.16.0 ,ssl证书,XXXX.jar 0.自行在阿里云上下载免费的ssl证书.里面有2个文件.key和pem后面要用到. 1.首先将项目在linux上跑起来 ...

  2. Lambda Expression

    Java 8的一个大亮点是引入Lambda表达式,使用它设计的代码会更加简洁.当开发者在编写Lambda表达式时,也会随之被编译成一个函数式接口.下面这个例子就是使用Lambda语法来代替匿名的内部类 ...

  3. 初步学习python

    自计算机诞生以来,也伴随着计算机语言的诞生,现在,全世界的编程语言有600多种,但流行的编程语言也就20多种. Java和C一直占据着前两名.但是近年来伴随着人工智能的发展,Python发展迅猛,以其 ...

  4. linux基础命令--groupdel 删除群组

    描述 groupdel命令用于删除用户组. groupdel命令会去修改系统下的/etc/group和/group/gshadow文件,删除有关用户组的所有项目(一般来说使用groupadd或user ...

  5. npm run dev没反应

    npm config set registry https://registry.npm.taobao.org npm install npm run dev

  6. Port Channel and VPC

    1.Port Channel 介绍 Port Channel  简介 绑定多个物理链路(最多8条),到一个单一的逻辑链路,在两个物理设备之间 每个物理端口只能被放入一个port-channel中. 在 ...

  7. 移动端适配--flexible.js

    引言: H5适配一直是一个比较普遍的问题,很多文章都会讲,最近开发了一个H5的项目使用了一下淘宝的 flexible.js,写一篇文章自己总结一下. 一.背景介绍: Flexible.js是淘宝公开的 ...

  8. 20190423 PowerDesigner 数据库模型快速建立

    后面我在做一个视频的讲解记录吧! 那种讲解记录,只是为了演示按钮功能在什么地方,这个功能的作用是什么 这个软件相对比较简单的使用步骤,主要有三步 第一. 选择好你针对的数据库版本和类型创建数据库名称基 ...

  9. Python之socketserver

    import threading from socketserver import ThreadingTCPServer,BaseRequestHandler import sys import lo ...

  10. Vue系列之 => webpack-babel的配置

    安装 cnpm i babel-core@6.26.3 babel-loader@7.0.0 babel-plugin-transform-runtime -D cnpm i babel-preset ...