记一次hashMap遍历时删除异常

在使用hashMap的过程中遇到的一个问题,记录一下。
之前在做一个功能的时候,需要删除hashMap中的一些元素,当时最先想到的方案就是直接for循环,然后在循环中调用remove方法删除元素,如下所示;

HashMap<String,String> map = new HashMap();
        map.put("11","1");
        map.put("22","2");
        for (String key : map.keySet()) {
            if ("11".equals(key))
                map.remove(key);
        }

运行代码后就抛出如下异常:
在这里插入图片描述
后来在网上查了一些资料,并查看了一些源码。
原因是每次我们对hashmap进行修改操作时都会由一个modCount变量记录修改次数;
hashmap调用for循环的时候底层还是创建了一个迭代器
迭代器创建时会将 expectedModCount = modCount;
在这里插入图片描述
在上面报错代码中,我对hashmap进行了一次remove操作,modCount的值就会加1,比如说我们上面进行了两次put操作,modCount的值为2,再执行remove之后,modCount的值为3,但是在创建迭代器时,modCount将值赋给了expectedModCount,此时expectedModCount的值为2;
在这里插入图片描述
当下次循环时迭代器会去调用它的next()方法
在这里插入图片描述
next()方法中调用了nextNode()方法
nextNode方法
此时会去校验modCount和expectedModCount的值是否相等,如果不相等就会抛出ConcurrentModificationException()异常。

解决方案:
要解决这个问题可以调用iterator迭代器的remove()方法。

  HashMap<String,String> map = new HashMap();
        map.put("11","1");
        map.put("22","2");
//        for (String key : map.keySet()) {
//            if ("11".equals(key))
//                map.remove(key);
//        }
        Iterator<String> iterator = map.keySet().iterator();
        while (iterator.hasNext()) {
            String next = iterator.next();
            if ("11".equals(next)){
                iterator.remove();
            }

此时代码可以正常运行。
我们来看一下iterator的remove()方法;
在这里插入图片描述
在执行完删除操作后会再次将modCount的值赋值给expectedModCount。

以下是我的一些猜想:
因为hashmap是一个线程不安全的集合,为了防止在并发情况下,一个线程在循环时,另一个线程对hashMap集合进行修改操作而设计的。(fast-fail 快速失败的机制)。
所以这个异常叫ConcurrentModificationException()并发修改异常;

但是在单线程情况下,一些不恰当的操作也会触发这个异常。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值