集合框架之——迭代器并发修改异常ConcurrentModificationException

时间:2023-01-03 15:00:51

问题:
我有一个集合,如下,请问,我想判断里面有没有”world”这个元素,如果有,我就添加一个”javaee”元素,请写代码实现。

使用普通迭代器出现的异常:
ConcurrentModificationException:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。

产生的原因:
迭代器是依赖于集合而存在的,在判断成功后,集合的中新添加了元素,而迭代器却不知道,所以就报错了,这个错叫并发修改异常。
其实这个问题描述的是:普通迭代器遍历元素的时候,通过集合是不能修改元素的。

解决:
A:迭代器迭代元素,迭代器修改元素
   元素是跟在刚才迭代的元素后面的。
B:集合遍历元素,集合修改元素(普通for循环进行遍历)
   元素是在最后添加的。

 import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator; public class ListIteratorDemo2 {
public static void main(String[] args) {
// 创建List集合对象
List list = new ArrayList();
// 添加元素
list.add("hello");
list.add("world");
list.add("java"); // 普通迭代器遍历
// Iterator it = list.iterator();
// while (it.hasNext()) {
// String s = (String) it.next();
// if ("world".equals(s)) {
// list.add("javaee"); //这里报错!!!!
// }
// } 方式1:迭代器迭代元素,迭代器修改元素
而Iterator迭代器却没有添加功能,所以我们使用其子接口ListIterator
ListIterator lit = list.listIterator();
while (lit.hasNext()) {
String s = (String) lit.next();
if ("world".equals(s)) {
lit.add("javaee");
}
} 方式2:集合遍历元素,集合修改元素(普通for)
for (int x = 0; x < list.size(); x++) {
String s = (String) list.get(x);
if ("world".equals(s)) {
list.add("javaee");
}
} System.out.println("list:" + list);
}
}

另外,尤其值得注意的是此迭代器remove()方法的使用:从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。每次调用 next 只能调用一次此方法。如果进行迭代时用调用此方法(remove方法)之外的其他方式修改了该迭代器所指向的 collection,则迭代器的行为是不确定的。 接口设计人员在设计Iterator<T>接口的时候已经指出,在进行迭代时如果调用了除了迭代器的remove()方法修改了该迭代器所指向的collection,则会造成不确定的后果。具体出现什么后果依迭代器的具体实现而定。针对这种不确定的后果可能出现的情况,在学习ArrayList时遇到了其中一种:迭代器抛出 ConcurrentModificationException异常。具体异常情况如下代码所示:

 import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator; public class ItaratorTest { public static void main(String[] args) {
Collection<String> list = new ArrayList<String>();
list.add("Android");
list.add("IOS");
list.add("Windows Mobile"); Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String lang = iterator.next();
list.remove(lang);//will throw ConcurrentModificationException
}
} }

此段代码在运行时会抛出ConcurrentModificationException异常,因为我们在迭代器运行期间没有用iterator的remove()方法来删除元素,而是使用ArrayList的 remove()方法改变了迭代器所指向的collection。这就违反了迭代器的设计原则,所以发生了异常。

总结:

  • 在用迭代器Iterator遍历collection时,如果要在遍历期间修改collection,则必须通过Iterator/listIterator来实现,否则可能会发生“不确定的后果”。

集合框架之——迭代器并发修改异常ConcurrentModificationException的更多相关文章

  1. 理解和解决Java并发修改异常ConcurrentModificationException&lpar;转载&rpar;

    原文地址:https://www.jianshu.com/p/f3f6b12330c1 理解和解决Java并发修改异常ConcurrentModificationException 不知读者在Java ...

  2. 大杂烩 -- Iterator 并发修改异常ConcurrentModificationException

    基础大杂烩 -- 目录 大杂烩 -- Java中Iterator的fast-fail分析 大杂烩 -- Iterator 和 Iterable 区别和联系 问题: 在集合中,判断里面有没有" ...

  3. 理解和解决Java并发修改异常&colon;ConcurrentModificationException

    參考文獻:https://www.jianshu.com/p/f3f6b12330c1 文獻来源:简书 关键字: Java Exception遇到异常信息Exception in thread &qu ...

  4. 并发修改异常ConcurrentModificationException

    1.简述:在使用 迭代器对象遍历集合时,使用集合对象修改集合中的元素导致出现异常 public static void main(String[] args) { List<Integer&gt ...

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

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

  6. java 15 - 8 集合框架(并发修改异常的产生原因以及解决方案)

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

  7. ConcurrentModificationException 集合并发修改异常 解决

    import java.util.ArrayList; import java.util.List; import java.util.ListIterator; /** * 问题? * 有一个集合, ...

  8. ConcurrentModificationException(并发修改异常)的解决

    [异常解释] ConcurrentModificationException:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常.[产生的原因] 迭代器是依赖于集合而存在的,在判断成功后,集合 ...

  9. 并发修改异常(ConcurrentModificationException)

    并发修改异常(ConcurrentModificationException) 这个异常,使用集合的时候应该很常见,这个异常产生的原因是因为java中不允许直接修改集合的结构. 先贴上个有趣的例子,给 ...

随机推荐

  1. 3、NAT

    <计算机网络(第5版)>P173    P182

  2. dubbo 试用全过程

    概述: dubbo服务容器是一个standalone的启动程序,因为后台服务不需要Tomcat或JBoss等Web容器的功能,如果硬要用Web容器去加载服务提供方,增加复杂性,也浪费资源. 服务容器只 ...

  3. windows条件下,Ping加上时间戳,并保存到文件,适用于测试网络

    在c盘下面新建文件 ping.vbs 在 ping.vbs中输入代码如下: Dim args, flag, unsuccOut args="" otherout="&qu ...

  4. COM编程入门第二部分——深入COM服务器

    本文为刚刚接触COM的程序员提供编程指南,解释COM服务器内幕以及如何用C++编写自己的接口.继上一篇COM编程入门之后,本文将讨论有关 COM服务器的内容,解释编写自己的COM接口和COM服务器所需 ...

  5. 计算方法(二)用C&num;实现数值积分

    在工程中,经常会遇到积分问题,这时原函数往往都是找不到的,因此就需要用计算方法的数值积分来求. public class Integral { /// <summary> /// 梯形公式 ...

  6. tabbar加小红点

    原文   http://blog.csdn.net/u013531246/article/details/44460115 #import <UIKit/UIKit.h> @interfa ...

  7. VMware Linux 下 Nginx

    负载   VMware Linux 下 Nginx 安装配置 - nginx.conf 配置 [负载两个 Tomcat] (三) Weiseditor 2014-11-26 23:42 阅读:1 评论 ...

  8. 【二代示波器教程】第15章 FreeRTOS操作系统版本二代示波器实现

    第15章     FreeRTOS操作系统版本二代示波器实现 本章教程为大家讲解FreeRTOS操作系统版本的二代示波器实现.主要讲解RTOS设计框架,即各个任务实现的功能,任务间的通信方案选择,任务 ...

  9. POJ3686 The Windy&&num;39&semi;s

    嘟嘟嘟 刚做费用流,思路完全不对呀-- 应该这么想(应该说敢这么想):这道题的关键在于怎么体现这个玩具是第几个加工的,只有这才能求出他的加工时间(因为加工时间包括等待时间). 但等待时间不好求,因此要 ...

  10. How to resolve &quot&semi;your security settings have blocked an untrusted application from running&quot&semi; in Mac

    If you encounter the error "your security settings have blocked an untrusted application from r ...