现在有一个需求,要遍历一个List,假设List里面存储的是String对象,然后该需求事判断里面如果有某个对象,则添加一个新的对象进去。自然,我们得出下面的代码:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; /**
* Created by lili on 15/11/13.
*/
public class Test {
public static void main(String[] args) {
List list = new ArrayList();
list.add("lucy");
list.add("polo");
list.add("shery"); //Exception in thread "main" java.util.ConcurrentModificationException
Iterator it = list.iterator();
while (it.hasNext()){
String str = (String)it.next();
if(str.equals("polo")){
list.add("pony");
}
}
}
}

但是该段代码会报错:ConcurrentModificationException,在API中查询这个异常,解释如下:

public class ConcurrentModificationException
extends RuntimeException
当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。 例如,某个线程在 Collection 上进行迭代时,通常不允许另一个线性修改该 Collection。通常在这些情况下,迭代的结果是不确定的。如果检测到这种行为,一些迭代器实现(包括 JRE 提供的所有通用 collection 实现)可能选择抛出此异常。执行该操作的迭代器称为快速失败 迭代器,因为迭代器很快就完全失败,而不会冒着在将来某个时间任意发生不确定行为的风险。 注意,此异常不会始终指出对象已经由不同 线程并发修改。如果单线程发出违反对象协定的方法调用序列,则该对象可能抛出此异常。例如,如果线程使用快速失败迭代器在 collection 上迭代时直接修改该 collection,则迭代器将抛出此异常。 注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败操作会尽最大努力抛出 ConcurrentModificationException。因此,为提高此类操作的正确性而编写一个依赖于此异常的程序是错误的做法,正确做法是:ConcurrentModificationException 应该仅用于检测 bug。 从以下版本开始:
1.2

从这个异常的说明来看,这种异常还不单单对List,是对所有的Collection容器(List,Set),如果在迭代的时候有修改,则都会出现。

那怎样才能解决这个问题呢?

  1. 用迭代器自身去添加对象,但是要利用ListIterator进行添加:Iterator只有hashNext,next和remove方法,而ListIterator有add和向前遍历的方法。
  2. 改用for循环来遍历判断并添加。
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator; /**
* Created by lili on 15/11/13.
*/
public class Test {
public static void main(String[] args) {
List list = new ArrayList();
list.add("lucy");
list.add("polo");
list.add("shery"); //Exception in thread "main" java.util.ConcurrentModificationException
// Iterator it = list.iterator();
// while (it.hasNext()){
// String str = (String)it.next();
// if(str.equals("polo")){
// list.add("pony");
// }
// } ListIterator listIt = list.listIterator();
while (listIt.hasNext()){
String str = (String) listIt.next();
if(str.equals("polo")){
listIt.add("pony");
}
if(str.equals("shery")){
listIt.add("keity");
}
} System.out.println(list); for(int i = 0; i < list.size(); i++){
if(list.get(i).equals("polo")){
list.add("pony");
}
if(list.get(i).equals("shery")){
list.add("keity");
}
} System.out.println(list);
}
}

但是从打印的结果来看,这两种添加还是有区别的,第一种方式是在当前遍历元素后面添加,第二种是在最后面追加。

[lucy, polo, pony, shery, keity]
[lucy, polo, pony, shery, keity, pony, keity] Process finished with exit code 0

【Java基础】List迭代并修改时出现的ConcurrentModificationException问题的更多相关文章

  1. 【死磕 Java 基础】 — 谈谈那个写时拷贝技术(copy-on-write)

    copy-on-write,即写时复制技术,这是小编在学习 Redis 持久化时看到的一个概念,当然在这个概念很早就碰到过(Java 容器并发有这个概念),但是一直都没有深入研究过,所以趁着这次机会对 ...

  2. java基础面试题:运行时异常与一般异常有何异同?error和exception有什么区别? 请写出你最常见到的5个runtimeexception?

    Throwable是Java错误处理的父类,有两个子类:Error和Exception. Error:无法预期的严重错误,导致JVM虚拟机无法继续执行,几乎无法恢复捕捉的 Exception:可恢复捕 ...

  3. Java基础 throws 提示调用方法时要注意处理相关异常

        JDK :OpenJDK-11      OS :CentOS 7.6.1810      IDE :Eclipse 2019‑03 typesetting :Markdown   code ...

  4. Java基础知识强化之集合框架笔记19:List集合迭代器使用之 并发修改异常的产生原因 以及 解决方案

    1. 我有一个集合,如下,请问,我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现. ConcurrentModi ...

  5. 微冷的雨Java基础学习手记(一)

    使用Java理解程序逻辑 之凌波微步 船舶停靠在港湾是很安全的,但这不是造船的目的 北大青鸟五道口原玉明老师出品 1.学习方法: 01.找一本好书 初始阶段不适合,可以放到第二个阶段,看到知识点时,要 ...

  6. Java基础应用

    Java集合类解析 List.Map.Set三个接口,存取元素时,各有什么特点? List 以特定次序来持有元素,可有重复元素.Set 无法拥有重复元素,内部排序.Map 保存key-value值,v ...

  7. Java基础进阶整理

    Java学习笔记整理 本文档是我个人整理的,首先是想通过完成本文档更加扎实自己的基础加强对java语言的理解,然后就是想给入了门的同志们做下贡献. 当然,本文档主要是对java语言基础(当然还有很多基 ...

  8. Java基础常见英语词汇

    Java基础常见英语词汇(共70个) ['ɔbdʒekt] ['ɔ:rientid]导向的                             ['prəʊɡræmɪŋ]编程 OO: object ...

  9. [Java面试二]Java基础知识精华部分.

    一:java概述(快速浏览): 1991 年Sun公司的James Gosling等人开始开发名称为 Oak 的语言,希望用于控制嵌入在有线电视交换盒.PDA等的微处理器: 1994年将Oak语言更名 ...

随机推荐

  1. wpf 只在window是ShowDialog打开时才设置DialogResult

    //only set DialogResult when window is ShowDialog before if(System.Windows.Interop.ComponentDispatch ...

  2. C#委托的语法

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using Delegate; na ...

  3. ext combobox getValue

    使用combobox时,它有一个hiddenName的属性,专门用于提交combobox中value的值. 现假设某combobox的Id为comboId,hiddenName属性的值为hiddenV ...

  4. oracle----复制表中的数据

    两种方法: 1. 在创建表的时候将数据从其他表中复制过来(并且表的结构也复制过来): 语法: CREATE TABLE table_name AS SELECT column1,......|* FR ...

  5. POJ2222+暴力搜索

    一共2^15个状态 比较简单 /* 2^15 states */ #include<stdio.h> #include<string.h> #include<stdlib ...

  6. mysql通过frm+ibd文件还原data

    此方法只适合innodb_file_per_table          = 1 当误删除ibdata 该怎么办? 如下步骤即可恢复: 1.准备工作 1)准备一台纯洁的mysql环境[从启动到现在没有 ...

  7. 修改Tomcat内存大小

    Windows下,在文件/bin/catalina.bat,Linux下,在文件/bin/catalina.sh的前面,增加如下设置: JAVA_OPTS=-Xms[初始化内存大小] -Xmx[可以使 ...

  8. wordpress的使用

    ubuntu 发送邮件学习资料: http://edu.51cto.com/lesson/id-6066.html 相关插件: Disable Google Fonts 使用中出现的问题: 1:wor ...

  9. ruby的命名约定

    1 局部变量和方法参数以小写字母开头 2 方法名字以小写字母开头 3 全局变量以$开头 4 实例变量以@开头 5 类变量以@@开头 6 常量以大写字母开头 7  类和模块名以大写字母开头

  10. URAL1658. Sum of Digits(DP)

    链接 这题卡了挺久了 昨天试着用类似dfs的方法直接TLE在第二组 看了下题解,,发现s1,s2的范围是个幌子..100位最大的s1900 s28100 觉得s1s2太大不敢开二维.. 这样就简单了 ...