JAVA List 一边遍历一边删除元素,报java.util.ConcurrentModificationException异常

2015年02月10日 14:42:49 zhanzkw 阅读数:3016更多

个人分类: JAVA
 

在使用set/map时,一个可爱的小bug:java.util.ConcurrentModificationException

【错误场景1】:set容器,边遍历,边add/remove元素

Set<String> set = new HashSet<String>();
for (int i = 0; i < 10000; i++) {
    set.add(Integer.toString(i));
}
for (String str : set) { //或使用iterator来循环,JDK5.0以上,这样的遍历底层也都是iterator实现。
    set.add("xxx"); //报错
//  set.remove(str); //报错
}
【错误场景2】:map容器,边遍历,边remove元素
Map<String, String> map = new HashMap<String, String>();
for (int i = 0; i < 100; i++) {
    map.put(Integer.toString(i), Integer.toString(i));
}
for (String str : map.keySet()) {//或使用iterator来循环
    map.remove(str); //报错
}
【错误场景3】list容器,边遍历,边add/remove元素
List<String> list = new ArrayList<String>();
        for (int i = 0; i < 100; i++) {
            list.add(Integer.toString(i));
        }
        for (Iterator<String> it = list.iterator(); it.hasNext();) { 
            String val = it.next();
            if (val.equals("5")) {
                list.add(val); //报错
                //     list.remove(val);   //报错    
            }
        }
 

【错误原因】

  • 对于remove操作,list.remove(o)的时候,只将modCount++,而expectedCount值未变,那么迭代器在取下一个元素的时候,发现该二值不等,则抛ConcurrentModificationException异常。
  • 对于add操作,同remove

【解决办法】

  • remove:用iterator提供的原生态remove()
  • add:同remove就错了,iterator没有提供原生的add()方法。真是的,还要用新的容器暂存,然后再遍历结束后,全部添加到原容器当中。

  • set/list:这两类常用容器,就用上面说的方法remove(), add()就好了。

  • map:直接使用ConcurrentHashMap就ok。为什么别的容器,不也实现个concurrent版本直接用。。?库里不搞,自己搞。

【正确使用案例】

for (Iterator<String> it = list.iterator(); it.hasNext();) {
    String val = it.next();
    if (val.equals("5")) {
        it.remove(); 
    }
}
List<String> newList = new ArrayList<String>(); 
for (Iterator<String> it = list.iterator(); it.hasNext();) {
    String val = it.next();
    if (val.equals("5")) {
        newList.add(val);
    }
}
list.addAll(newList);

转载自:http://www.cnblogs.com/alipayhutu/archive/2012/04/23/2465981.html

正确使用案例二:

  1. public class Test {
  2. public static void main(String[] args) {
  3. User user1 = new User();
  4. user1.setId(1);
  5. user1.setName("shangsan");
  6.  
  7. User user2 = new User();
  8. user2.setId(2);
  9. user2.setName("lisi");
  10.  
  11. List<User> list = new ArrayList<User>();
  12. list.add(user1);
  13. list.add(user2);
  14.  
  15. System.out.println("userSet.size() before--------------"+list.size());
  16.  
  17. List<User> delList = new ArrayList<User>();
  18. for (Iterator<User> it = list.iterator(); it.hasNext();) {
  19. User user = (User) it.next();
  20. if (user.getId() == 1) {
  21. delList.add(user);
  22. }
  23.  
  24. }
  25. list.removeAll(delList);
  26.  
  27. System.out.println("userSet.size() after--------------"+list.size());
  28. }
  29. }

JAVA List 一边遍历一边删除元素的更多相关文章

  1. java list集合遍历时删除元素

    转: java list集合遍历时删除元素 大家可能都遇到过,在vector或arraylist的迭代遍历过程中同时进行修改,会抛出异常java.util.ConcurrentModification ...

  2. 【Java】List遍历时删除元素的正确方式

    当要删除ArrayList里面的某个元素,一不注意就容易出bug.今天就给大家说一下在ArrayList循环遍历并删除元素的问题.首先请看下面的例子: import java.util.ArrayLi ...

  3. java 集合list遍历时删除元素

    本文探讨集合在遍历时删除其中元素的一些注意事项,代码如下 import java.util.ArrayList; import java.util.Iterator; import java.util ...

  4. Java HashMap 如何正确遍历并删除元素

    (一)HashMap的遍历 HashMap的遍历主要有两种方式: 第一种采用的是foreach模式,适用于不需要修改HashMap内元素的遍历,只需要获取元素的键/值的情况. HashMap<K ...

  5. Java中ArrayList循环遍历并删除元素的陷阱

    ava中的ArrayList循环遍历并且删除元素时经常不小心掉坑里,昨天又碰到了,感觉有必要单独写篇文章记一下. 先写个测试代码: import java.util.ArrayList; public ...

  6. 【转】ArrayList循环遍历并删除元素的常见陷阱

    转自:https://my.oschina.net/u/2249714/blog/612753?p=1 在工作和学习中,经常碰到删除ArrayList里面的某个元素,看似一个很简单的问题,却很容易出b ...

  7. ArrayList循环遍历并删除元素的常见陷阱

    在工作和学习中,经常碰到删除ArrayList里面的某个元素,看似一个很简单的问题,却很容易出bug.不妨把这个问题当做一道面试题目,我想一定能难道不少的人.今天就给大家说一下在ArrayList循环 ...

  8. 【原理探究】女朋友问我ArrayList遍历时删除元素的正确姿势是什么?

    简介 我们在项目开发过程中,经常会有需求需要删除ArrayList中的某个元素,而使用不正确的删除方式,就有可能抛出异常.或者在面试中,会遇到面试官询问遍历时如何正常删除元素.所以在本篇文章中,我们会 ...

  9. js 遍历集合删除元素

    js 遍历集合删除元素 /** * 有效的方式 - 改变下标,控制遍历 */ for (var i = 0; i < arr.length; i++) { if (...) { arr.spli ...

随机推荐

  1. 国内maven库链接地址,链接阿里的库,下载很快!!!

    <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http:/ ...

  2. Jackson 触发的String.intern() bug, 导致内存持续增加,JVM-Java内存泄漏

    我在本地用Jackson可以复现这个问题了. import java.io.IOException; import java.util.Map; import java.util.Random; im ...

  3. Altera Stratix IV 命名规则

    由于要开发基于DE4平台的应用,应该要了解一下该平台的芯片情况Stratix IV 具体型号为:Stratix IV EP4SGX230KF40C2 命名规范如下 官网资料为:https://www. ...

  4. java加密用到了BASE64Decoder时报错信息:Access restriction: The type BASE64Encoder is not accessible due to restrict

    在Eclipse中编写Java代码时,用到了BASE64Decoder,import sun.misc.BASE64Decoder;可是Eclipse提示: Access restriction : ...

  5. 生成Excel.xlsx文件 iOS

    使用到的三方库 https://github.com/jmcnamara/libxlsxwriter cocoapods导入 pod 'libxlsxwriter', '~> 0.8.3' 1. ...

  6. 手把手教你写css3通用动画

    之前接了几个微信里的项目,类似电子邀请函,什么分析报告这样的项目, 对css3动画要求十分高,每个页面客户几乎都有天马行空的想法,或者说设计师有这样的想法.众所周知css3里的keyframe写好了就 ...

  7. Scala学习笔记(一):环境搭建

    计算机领域的编程语言种类繁多,如C.C++.Java.C#等,我们知道的一般都是较为流行的编程语言,然有更多的是没听说过的,于是也就说不上关注或者使用了 一次在网上查资料时,无意间看到了“函数式编程” ...

  8. 子串查询(二维前缀数组) 2018"百度之星"程序设计大赛 - 资格赛

    子串查询 Time Limit: 3500/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Subm ...

  9. 初探 Qt Opengl【2】

    最近在研究QOPengl QGraphicsView QGraphicsItemQGraphicsScene不过也只是皮毛,也不是做什么技术贴,就是记录一下自己在其中遇到的问题,和自己新学到的东西. ...

  10. 对TPR(真正例率) 与 FPR(反正例率)的理解

    将测试样本进行排序,“最可能”是正例的排在最前面,“最不可能”是正例的排在最后面. 分类过程就相当于在这个排序中以某个“截断点”(见图中阈值)将样本分为两部分,前一部分判作正例,后一部分判作反例. 我 ...