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;也就是重新迭代,结果,不报错了,但是数据好像是不对。

扫描二维码关注公众号,回复: 14990455 查看本文章

很是疑惑,于是我断点调试,明白了,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)函数来添加元素,也会出现同样的问题,所以同样需要使用迭代器的相应函数来添加。

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

猜你喜欢

转载自blog.csdn.net/yeziyfx/article/details/116797398