`
zhongkem
  • 浏览: 148983 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

从集合类中删除元素时容易碰到的问题(ConcurrentModificationException)

阅读更多

先看下面的一段代码,也许很多人都会觉得没任何问题:

  Set<String> myset= new HashSet<String>();
    myset.add("apple");
    myset.add("orange");
    Iterator it = myset.iterator();
    while(it.hasNext()) {
        String fruit=(String) it.next();
       if(fruit.equals("apple")) 
          myset.remove(fruit);    //wrong
    }

 

 但实际运行中会抛ConcurrentModificationException异常。。从网上搜了下,摘抄如下:

当使用 fail-fast iterator 对 Collection 或 Map 进行迭代操作过程中尝试直接修改 Collection / Map 的内容时,即使是在单线程下运行,   java.util.ConcurrentModificationException 异常也将被抛出。

  Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。

  所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。

  有意思的是如果你的 Collection / Map 对象实际只有一个元素的时候, ConcurrentModificationException 异常并不会被抛出。这也就是为什么在 javadoc 里面指出: it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.

    因此,想让上面的代码正常运行,可以采用下面的方式:

  Set<String> myset= new HashSet<String>();
    myset.add("apple");
    myset.add("orange");
    Iterator it = myset.iterator();
    while(it.hasNext()) {
        String fruit=(String) it.next();
       if(fruit.equals("apple")) 
          it.remove();    //right
    }

 

这种问题应该特别注意。我以前就没注意过。。今天刚了解。。。以前写的代码不得不回去改!!!

 

分享到:
评论

相关推荐

    遍历并批量删除容器中元素出现ConcurrentModificationException原因及处置

    NULL 博文链接:https://chenlinbo.iteye.com/blog/832335

    java.util.ConcurrentModificationException 异常问题详解1

    java.util.ConcurrentModificationException 异常问题详解1

    java集合类面试题总结

    下面总结了 Java 集合类的一些常见问题和答案。 HashMap 和 Hashtable 的区别 HashMap 和 Hashtable 都是 Java 中的散列表实现,但它们有所不同。HashMap 允许一个 null 键和多个 null 值,而 Hashtable 不允许 ...

    collecter集合总结

    需要注意的是,在迭代的过程中不能对集合中元素进行修改,否则将产生 java.util.ConcurrentModificationException。 选择集合 在实际开发中,选择合适的集合是非常重要的。以下是一些选择集合的建议: * 如果需要...

    实现Java删除一个集合的多个元素

    Java中的For each实际上使用的是iterator进行处理的。而iterator是不允许集合在...而我在for each时,从集合中删除了一个元素,这导致了iterator抛出了ConcurrentModificationException,下面来看看到底怎么回事。

    出现java.util.ConcurrentModificationException 问题及解决办法

    主要介绍了出现java.util.ConcurrentModificationException 问题及解决办法的相关资料,需要的朋友可以参考下

    java集合-CopyOnWriteArraySet的使用

    CopyOnWriteArraySet 是Java中的一个线程安全的集合类,它实现了 Set 接口并使用了"写时复制"的机制。 下面是关于 CopyOnWriteArraySet 的一些重要信息: 线程安全性:CopyOnWriteArraySet 是线程安全的,可以在多...

    java 集合并发操作出现的异常ConcurrentModificationException

    Map在遍历时候通常 现获得其键值的集合Set,然后用迭代器Iterator来对Map进行遍历。

    多线程中使用Java集合类

    Java集合类中,某个线程在 Collection 上进行迭代时,通常不允许另一个线性修改该 Collection。通常在这些情况下,迭代的结果是不确定的。如果检测到这种行为,一些迭代器实现(包括 JRE 提供的所有通用 collection ...

    java.util.ConcurrentModificationException 解决方法

    在使用iterator.hasNext()操作迭代器的时候,如果此时迭代的对象发生改变,比如插入了新数据,或者有数据被删除。 则使用会报以下异常: Java.util.ConcurrentModificationException at java.util.HashMap$...

    Java语言的Util类详细介绍

    但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除元素),Iterator将抛出ConcurrentModificationException异常。 Set接口是Collection接口的子接口...

    Iterator遍历过程中list删除导致异常

    Iterator遍历中 ConcurrentModificationException异常

    Java源码解析ArrayList及ConcurrentModificationException

    今天小编就为大家分享一篇关于Java源码解析ArrayList及ConcurrentModificationException,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

    axis1.4.1.zip

    axis1.4补丁包,解决jdk1.8高并发报ConcurrentModificationException问题,该jar包重新编译jar包的一个class文件,线上环境通过

    超级有影响力霸气的Java面试题大全文档

     栈是一种线形集合,其添加和删除元素的操作应在同一段完成。栈按照后进先出的方式进行处理。 堆是栈的一个组成元素 22、forward 和redirect的区别  forward是服务器请求资源,服务器直接访问目标地址的URL,把...

    java8集合源码-zinc-ConcurrentModificationException:锌并发修改异常

    java8集合源码sbt run 锌抛: [info] running example.MainClass [info] compiling 1 Java source to C:\Users\Chikei\AppData\Local\Temp\zincClasses336102448129471145 ... [error] ## Exception when compiling ...

    fail-safe fail-fast知多少

    我们在使用集合类的时候,通常会需要去遍历集合中的元素,并在遍历中对其中的元素进行处理。这时候我们就要用到Iterator,经常写程序的朋友应该都知道,在Iterator遍历的过程中,是不能够修改集合数据的,否则就会抛...

    java 面试题 总结

    栈是一种线形集合,其添加和删除元素的操作应在同一段完成。栈按照后进先出的方式进行处理。 堆是栈的一个组成元素 19、forward 和redirect的区别 forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL...

    Java开发常见问题总结.docx

    避免在循环中修改集合,可能导致ConcurrentModificationException。 异常处理: 不要忽视异常,合理捕获并处理它们。 不要过度使用try-catch,应尽量抛出业务异常给上层处理。 使用finally块进行资源清理。 并发...

Global site tag (gtag.js) - Google Analytics