【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语言更名 ...
随机推荐
- 虚拟机添加磁盘LVM分区
参考博客:http://kimjinlsgd.blog.51cto.com/1918030/932210 一.查看磁盘情况 新添加一块磁盘. [root@VMhost /]# fdisk -l Dis ...
- 折腾了一早上的C# WPF ListView+Grid 实现图片+文字 自动换行排列 类似Windows资源管理器效果
<ListBox Name="lstFileManager" Background ="Transparent" ItemsSource="{B ...
- 【BZOJ】1088: [SCOI2005]扫雷Mine
1088: [SCOI2005]扫雷Mine Description 相 信大家都玩过扫雷的游戏.那是在一个n*m的矩阵里面有一些雷,要你根据一些信息找出雷来.万圣节到了,“余”人国流行起了一种简单的 ...
- 一步步学习ASP.NET MVC3 (9)——JsonReslt,JavaScript,@Ajax
请注明转载地址:http://www.cnblogs.com/arhat 在上一章中,我们讲述了ActionResult的三个子类,非别是EmptyResult,RediretResult和Conte ...
- .net 添加不同项目框架引用出现的问题
问题描述: winform项目添加web项目时出现问题,winform项目添加web项目类时,老是报找不到这个类的命名空间 最后才知道两个项目所建的框架不一样,一个是.net framework 4, ...
- JavaScript跨站脚本攻击
跨站脚本攻击(Cross-Site Scrpting)简称为XSS,指的是向其他域中的页面的DOM注入一段脚本,该域对其他用户可见.恶意用户可能会试图利用这一弱点记录用户的击键或操作行为,以窃取用户的 ...
- C#.NET连接mysql方法
C#访问MySQL数据库的方法 (1)首先需要下载C#访问MySQL数据库的ADO.NET驱动程序 下载地址为: http://dev.mysql.com/downloads/connector/ne ...
- PHP漏洞全解(二)-命令注入攻击
本文主要介绍针对PHP网站常见的攻击方式中的命令攻击.Command Injection,即命令注入攻击,是指这样一种攻击手段,黑客通过把HTML代码输入一个输入机制(例如缺乏有效验证限制的表格域)来 ...
- 使用JProfiler进行内存分析
在最近的工作中,通过JProfiler解决了一个内存泄漏的问题,现将检测的步骤和一些分析记录下来,已备今后遇到相似问题时可以作为参考. 运行环境: Tomcat6,jdk6,JProfiler8 内存 ...
- [topcoder]FoxAndChess
http://community.topcoder.com/stat?c=problem_statement&pm=12725&rd=15702 这题比较简单.首先所有的LR的顺序要一 ...