我是靠谱客的博主 彩色小天鹅,最近开发中收集的这篇文章主要介绍Hashmap遍历时用map.remove方法为什么会报错?,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

private static HashMap<Integer, String> map = new HashMap<Integer, String>();;
public static void main(String[] args) {
for(int i = 0; i < 10; i++){
map.put(i, "value" + i);
}
}
for(Map.Entry<Integer, String> entry : map.entrySet()){
Integer key = entry.getKey();
if(key % 2 == 0){
System.out.println("To delete key " + key);
map.remove(key);
System.out.println("The key " + + key + " was deleted");
}

        对HashMap进行遍历的时候,同时做了remove操作,这个操作最后导致抛出了java.util.ConcurrentModificationException的错误。

先看下源码,分析问题的原因

从报错中可以看出,HashMap$HashIterator.nextNode这个方法有代码错误了,点进去看,大概知道HashMap.this.modCount != this.expectedModCount 成立

再看一下hashmap的remove操作是做了什么:

        这里对modCount进行了自增操作,表示操作动作+1。

        再看modCount和expectedModCount是什么东西。

        可以看出迭代器初始化的时候就对modCount和expectedModCount进行同步。

到此,可以看出报错的原因:

        hashmap里维护了一个modCount变量,迭代器里维护了一个expectedModCount变量,一开始两者是一样的。

        每次进行hashmap.remove操作的时候就会对modCount+1,此时迭代器里的expectedModCount还是之前的值。

        在下一次对迭代器进行next()调用时,判断是否HashMap.this.modCount != this.expectedModCount,如果是则抛出异常。

那什么情况下在遍历的时候可以删除map里面的元素呢?看下迭代器提供的remove方法:

        可以看出迭代器里remove了一个元素之后会对expectedModCount重新赋值,这样再次遍历的时候就不会报错了。所以之前的代码可以改成如下写法,直接调用迭代器的remove方法。

 Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator();
while(it.hasNext()){
Map.Entry<Integer, String> entry = it.next();
Integer key = entry.getKey();
if(key % 2 == 0){
System.out.println("To delete key " + key);
it.remove();
System.out.println("The key " + + key + " was deleted");
}
}

总结:

        基本上java集合类(包括list和map)在遍历时没用迭代器进行删除了都会报ConcurrentModificationException错误,这是一种fast-fail的机制,初衷是为了检测bug。

        通俗一点来说,这种机制就是为了防止高并发的情况下,多个线程同时修改map或者list的元素导致的数据不一致,这是只要判断当前modCount != expectedModCount即可以知道有其他线程修改了集合。

替换机制:

  • 用迭代器的remove方法。
  • 用currentHashMap替代HashMap

 

最后

以上就是彩色小天鹅为你收集整理的Hashmap遍历时用map.remove方法为什么会报错?的全部内容,希望文章能够帮你解决Hashmap遍历时用map.remove方法为什么会报错?所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(64)

评论列表共有 0 条评论

立即
投稿
返回
顶部