引用于http://blog.csdn.net/dabing69221/article/details/40065071

在使用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);

java.util.ConcurrentModificationException详解的更多相关文章

  1. java并发包java.util.concurrent详解

    线程池ThreadPoolExecutor的使用 并发容器之CopyOnWriteArrayList 并发容器之CopyOnWriteArraySet 数据结构之ConcurrentHashMap,区 ...

  2. java.util包详解

    介绍Java的实用工具类库java.util包.在这个包中,Java提供了一些实用的方法和数据结构.本章介绍Java的实用工具类库java.util包.在这个包中,Java提供了一些实用的方法和数据结 ...

  3. Java.util.ArrayList详解

    java.util.ArrayList就是传说中的动态数组. 继承了关系,有此可看出ArrayList与list的collection的关系 public class ArrayList<E&g ...

  4. [转载] java多线程学习-java.util.concurrent详解(一) Latch/Barrier

    转载自http://janeky.iteye.com/blog/769965     Java1.5提供了一个非常高效实用的多线程包:java.util.concurrent, 提供了大量高级工具,可 ...

  5. [转载] java多线程学习-java.util.concurrent详解(二)Semaphore/FutureTask/Exchanger

    转载自http://janeky.iteye.com/blog/770393 ------------------------------------------------------------- ...

  6. [转载] java多线程学习-java.util.concurrent详解(三)ScheduledThreadPoolExecutor

    转载自http://janeky.iteye.com/blog/770441 ------------------------------------------------------------- ...

  7. [转载] java多线程学习-java.util.concurrent详解(四) BlockingQueue

    转载自http://janeky.iteye.com/blog/770671 ------------------------------------------------------------- ...

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

    环境:JDK 1.8.0_111 在Java开发过程中,使用iterator遍历集合的同时对集合进行修改就会出现java.util.ConcurrentModificationException异常, ...

  9. java.util.ConcurrentModificationException解决详解

    异常产生 当我们迭代一个ArrayList或者HashMap时,如果尝试对集合做一些修改操作(例如删除元素),可能会抛出java.util.ConcurrentModificationExceptio ...

随机推荐

  1. Python第一个GUI

    #!/usr/bin/python#coding=utf-8'''Created on 2017年11月2日 from home @author: James zhan ''' from functo ...

  2. python基础提高演练(名片管理系统的开发)

    综合应用 —— 名片管理系统 目标 综合应用已经学习过的知识点: 变量 流程控制 函数 模块 开发 名片管理系统 系统需求 1. 程序启动,显示名片管理系统欢迎界面,并显示功能菜单 ********* ...

  3. 神州数码多区域OSPF配置

    实验要求:掌握多区域OSPF配置 拓扑如下 R1 enable 进入特权模式 config 进入全局模式 hostname R1 修改名称 interface s0/1 进入端口 ip address ...

  4. ViewpageAdapter

    import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory; ...

  5. 4.python字符串格式化

    格式化字符串时,Python使用一个字符串作为模板.模板中有格式符,这些格式符为真实值预留位置,并说明真实数值应该呈现的格式.Python用一个tuple将多个值传递给模板,每个值对应一个格式符.py ...

  6. PHP处理上传文件信息数组中的文件类型 正确获取

    PHP处理上传文件信息数组中的文件类型$_FILES['type']由客户端浏览器提供,有可能是黑客伪造的信息,请写一个函数来确保用户上传的图像文件类型真实可靠 如果是一般文件则通过 mime_con ...

  7. 【工具】switchhost

    1.前提 主要功能切换host 2.下载路径 https://oldj.github.io/SwitchHosts/ 3.使用略(太简单)

  8. 使用miniconda创建python虚拟环境

    安装python指定环境 conda create -n oldboy python=3.6.5 安装环境的同时安装相应的包 conda create -n oldboy python=3.6.5 p ...

  9. [R] t.test()

    t.test(x, y = NULL, alternative = c("two.sided", "less","greater"), mu ...

  10. Office常用技巧

    文章目录 大小写切换 把word里的自动编号转换为真实的文本 大小写切换 word中修改单词/句子的大小写:选中文字,按shift+F3,可在全大写.全小写.首字符大写间切换. 把word里的自动编号 ...