【Java基础】List迭代并修改时出现的ConcurrentModificationException问题
现在有一个需求,要遍历一个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),如果在迭代的时候有修改,则都会出现。
那怎样才能解决这个问题呢?
- 用迭代器自身去添加对象,但是要利用ListIterator进行添加:Iterator只有hashNext,next和remove方法,而ListIterator有add和向前遍历的方法。
- 改用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问题的更多相关文章
- 【死磕 Java 基础】 — 谈谈那个写时拷贝技术(copy-on-write)
copy-on-write,即写时复制技术,这是小编在学习 Redis 持久化时看到的一个概念,当然在这个概念很早就碰到过(Java 容器并发有这个概念),但是一直都没有深入研究过,所以趁着这次机会对 ...
- java基础面试题:运行时异常与一般异常有何异同?error和exception有什么区别? 请写出你最常见到的5个runtimeexception?
Throwable是Java错误处理的父类,有两个子类:Error和Exception. Error:无法预期的严重错误,导致JVM虚拟机无法继续执行,几乎无法恢复捕捉的 Exception:可恢复捕 ...
- Java基础 throws 提示调用方法时要注意处理相关异常
JDK :OpenJDK-11 OS :CentOS 7.6.1810 IDE :Eclipse 2019‑03 typesetting :Markdown code ...
- Java基础知识强化之集合框架笔记19:List集合迭代器使用之 并发修改异常的产生原因 以及 解决方案
1. 我有一个集合,如下,请问,我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现. ConcurrentModi ...
- 微冷的雨Java基础学习手记(一)
使用Java理解程序逻辑 之凌波微步 船舶停靠在港湾是很安全的,但这不是造船的目的 北大青鸟五道口原玉明老师出品 1.学习方法: 01.找一本好书 初始阶段不适合,可以放到第二个阶段,看到知识点时,要 ...
- Java基础应用
Java集合类解析 List.Map.Set三个接口,存取元素时,各有什么特点? List 以特定次序来持有元素,可有重复元素.Set 无法拥有重复元素,内部排序.Map 保存key-value值,v ...
- Java基础进阶整理
Java学习笔记整理 本文档是我个人整理的,首先是想通过完成本文档更加扎实自己的基础加强对java语言的理解,然后就是想给入了门的同志们做下贡献. 当然,本文档主要是对java语言基础(当然还有很多基 ...
- Java基础常见英语词汇
Java基础常见英语词汇(共70个) ['ɔbdʒekt] ['ɔ:rientid]导向的 ['prəʊɡræmɪŋ]编程 OO: object ...
- [Java面试二]Java基础知识精华部分.
一:java概述(快速浏览): 1991 年Sun公司的James Gosling等人开始开发名称为 Oak 的语言,希望用于控制嵌入在有线电视交换盒.PDA等的微处理器: 1994年将Oak语言更名 ...
随机推荐
- WebLogic启动时报错
java.lang.ClassCastException: com.octetstring.vde.backend.BackendRoot cannot be cast to com.octetstr ...
- SQLServer数据库通用访问类
private static string connString=ConfigurationManager.ConnStrings["connString"].ToString() ...
- Python之创建单元素tuple
tuple和list一样,可以包含 0 个.1个和任意多个元素. 包含多个元素的 tuple,前面我们已经创建过了. 包含 0 个元素的 tuple,也就是空tuple,直接用 ()表示: >& ...
- VC项目配置基础以及快捷键(收藏)
来自http://blog.csdn.net/phunxm/article/details/5082488 一.IDE基础配置 1.字体 VC6中“Tools→Options→Format→Font” ...
- unity 引入 ios 第三方sdk
原地址:http://blog.csdn.net/u012085988/article/details/17785023 unity开发中ios应用时,要想成功引入第三方sdk,首先得知道c#与obj ...
- public void Delete(List EntityList) where T : class, new()类型参数约束
查找后发现这是类型参数约束,.NET支持的类型参数约束有以下五种: where T : struct | T必须是一个结构类型 where T : class T必须是一个类(class)类型 whe ...
- 总结: Struts2 + Spring 的线程安全问题
1. 首先Struts2 本身是安全的 其原理大概是:Strtus2会获取到用户的http请求,然后负责给每个请求实例化一个Action 对象,但是大家注意,这里的action对象和Struts1里面 ...
- 【HDOJ】3275 Light
这就是个简单线段树+延迟标记.因为对bool使用了~而不是!,wa了一下午找不到原因. /* 3275 */ #include <iostream> #include <sstrea ...
- Sublime Text各种插件使用方法
有快捷键冲突的时候可以修改快捷键,建议修改插件快捷键而不是Sublime Text的快捷键,我的有冲突的一律将插件快捷键设置成:Ctrl+Alt+A(B...) Package Control 通俗易 ...
- DesignPatterns
1.设计模式,说明工厂模式. 总共23种,分为三大类:创建型,结构型,行为型 创建型 1. Factory Method(工厂方法) 2. Abstract Factory(抽象工厂) 3. Bui ...