Java Map集合删除元素报错Java.util.ConcurrentModificationException的解决方案

前几天在写程序过程中,需要根据判断条件删除一个Map中的相应数据,我自然而然想到可以通过调用Map中的remove(Object key)函数进行删除:代码如下:

public void  processMap(Map list) {
        Map map = list;

       Iterator iter = map.keyset().iterator;

       while(iter.hasNext()) {
               double key = iter.next();

               if (key > 5){

                              map.remove(key);

               }

       }

}

但是运行程序的时候却没有正常删除元素,而是提示“Java.util.ConcurrentModificationException”错误,我想起了之前见到过这个错误的解释,好像是迭代器有问题了,但一时半会没记起怎么解决。

于是我曲线救国,在 map.remove(key);后加上iter = map.keyset().iterator;也就是重新迭代,结果,不报错了,但是数据好像是不对。

很是疑惑,于是我断点调试,明白了,map中的数据又重新从第一个迭代了。好吧,逻辑不对。百度一下,找到了原因和解决方案。我把人家的原文修改了一下格式,并对代码进行修正。

找了一些关于Map的资料发现:Map的实现不是同步的。

具体是:

      1.如果程序中出现多个线程同时访问一个Map,而其中至少一个线程修改Map时,它必须保持外部同步。

      2.而通过查看Iterator原理发现,Iterator是工作在一个独立的线程中,并且拥有一个 mutex锁,就是说Iterator在工作的时候,是不允许被迭代的对象被改变的,所以调用Iterator操作获得的对象在多线程修改Map的时候会自动失效。

     3.Iterator被创建的时候,建立了一个内存索引表(单链表),这 个索引表指向原来的对象,当原来的对象数量改变的时候,这个索

引表的内容没有同步改变,所以当索引指针往下移动的时候,便找不到要迭代的对象,于是产生错 误。

     4.Map、List、Set等是动态的,可变对象数量的数据结构,但是Iterator则是单向不可变,只能顺序读取,不能逆序操作的数据结构,当 Iterator指向的原始

数据发生变化时,Iterator自己就迷失了方向。

找到了问题的原因,那么如何解决呢?可以通过调用Iterator的remove()函数来移除元素。

测试代码如下:

public void processMap(Map list) {
                Map map = list;

                Iterator iter = map.keyset().iterator;

               while(iter.hasNext()) {
                                  double key = iter.next();

                                 if (key > 5) {
                                                  //   map.remove(key);  // java.util.ConcurrentModificationException

                                         iter.remove();  // OK

                                   }

                 }

}
同时,在遍历Map过程中,调用put(key, value)函数来添加元素,也会出现同样的问题,所以同样需要使用迭代器的相应函数来添加。

 

声明:本文内容绝大部分复制的别人的,原因一是原文格式和代码均不太易于观看,二是自己备份一下,便于翻阅。

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值