微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Java ConcurrentHashMap示例和迭代器

如果是Java开发者,那么必须知道在使用迭代器完成其所有元素时要修改Collection对象时出现会出现ConcurrentModificationException异常。 实际上Java Collection Framework迭代器是迭代器设计模式实现的很好的例子。

Java ConcurrentHashMap

Java 1.5引入了带有Collection类实现的java.util.concurrent包,允许在运行时修改集合对象。

ConcurrentHashMap示例

ConcurrentHashMap类是一个类似于HashMap的类,但在尝试在运行时修改映射时工作正常。

下面来运行一个示例程序来了解和熟悉,文件ConcurrentHashMapExample.java -


package com.jb51.cc.util;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapExample {

    public static void main(String[] args) {

        //ConcurrentHashMap
        Map<StringString> myMap = new ConcurrentHashMap<StringString>();
        myMap.put(1 1);
        myMap.put(2 1);
        myMap.put(3 1);
        myMap.put(4 1);
        myMap.put(5 1);
        myMap.put(6 1);
        System.out.println(ConcurrentHashMap before iterator: +myMap);
        Iterator<String> it = myMap.keySet().iterator();

        while(it.hasNext()){
            String key = it.next();
            if(key.equals(3)) myMap.put(key+new new3);
        }
        System.out.println(ConcurrentHashMap after iterator: +myMap);

        //HashMap
        myMap = new HashMap<StringString>();
        myMap.put(1 1);
        myMap.put(2 1);
        myMap.put(3 1);
        myMap.put(4 1);
        myMap.put(5 1);
        myMap.put(6 1);
        System.out.println(HashMap before iterator: +myMap);
        Iterator<String> it1 = myMap.keySet().iterator();

        while(it1.hasNext()){
            String key = it1.next();
            if(key.equals(3)) myMap.put(key+new new3);
        }
        System.out.println(HashMap after iterator: +myMap);
    }

}

当尝试运行上面的代码时,输出结果如下:

ConcurrentHashMap before iterator: {1=1 5=1 6=1 3=1 4=1 2=1}
ConcurrentHashMap after iterator: {1=1 3new=new3 5=1 6=1 3=1 4=1 2=1}
HashMap before iterator: {3=1 2=1 1=1 6=1 5=1 4=1}
Exception in thread main java.util.ConcurrentModificationException
    at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
    at java.util.HashMap$KeyIterator.next(HashMap.java:828)
    at com.test.ConcurrentHashMapExample.main(ConcurrentHashMapExample.java:44)

查看输出ConcurrentHashMap负责处理映射中的任何新条目,而HashMap抛出ConcurrentModificationException异常。

如果仔细看看异常堆栈跟踪,抛出Exception的语句是:

String key = it1.next();

这意味着新条目已插入HashMap,但Iterator执行失败。 实际上,Collection对象上的Iterator快速的,即结构中的任何修改或集合对象中的条目数都将触发Iterator抛出的此异常。

那么Iterator如何知道HashMap中有一些修改。 从HashMap获取了一组键,然后迭代它。

HashMap包含一个用于计算修改次数的变量,Iterator调用next()函数获取一个条目时使用它。

文件HashMap.java -


/**
     * The number of times this HashMap has been structurally modified
     * Structural modifications are those that change the number of mappings in
     * the HashMap or otherwise modify its internal structure (e.g.,
     * rehash).  This field is used to make iterators on Collection-views of
     * the HashMap fail-fast.  (See ConcurrentModificationException).
     */
    transient volatile int modCount;

现在要证明上述观点,在插入新条目时稍微更改代码以从迭代器循环中出来。需要做的就是在put调用之后添加一个break语句。


if(key.equals(3)){
    myMap.put(key+new, new3);
        break;
}

现在执行修改后的代码输出将是:


ConcurrentHashMap before iterator: {1=1, 5=1, 6=1, 3=1, 4=1, 2=1}
ConcurrentHashMap after iterator: {1=1, 3new=new3, 5=1, 6=1, 3=1, 4=1, 2=1}
HashMap before iterator: {3=1, 2=1, 1=1, 6=1, 5=1, 4=1}
HashMap after iterator: {3=1, 2=1, 1=1, 3new=new3, 6=1, 5=1, 4=1}

最后,如果不添加新条目但更新现有键值对会怎样,它也会抛出异常吗?

更改原始程序中的代码,如下所示 -


//myMap.put(key+new, new3);
myMap.put(key, new3);

这次应该没有问题了。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐