ConcurrentHashMap和HashMap的containsKey方法区别

来源:互联网 发布:linux复制文件和文件夹 编辑:程序博客网 时间:2024/05/22 03:03

一、背景

以null为key调用ConcurrentHashMap的containsKey方法时报空指针错误。

java.lang.NullPointerException    at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936)    at java.util.concurrent.ConcurrentHashMap.containsKey(ConcurrentHashMap.java:964)

二、ConcurrentHashMap和HashMap的containsKey方法区别

Map接口中containsKey方法定义如下:

public interface Map<K,V> {...    boolean containsKey(Object key);...}

containsKey方法接受一个Object类型的参数,因此所有类型的对象都可以作为containsKey方法的参数,甚至null,编译不会报错。但当Map接口的实现类中containsKey方法不接受null作为入参时,以null作为入参调用该方法将抛出NullPointerException。

ConcurrentHashMap和HashMap都实现了Map接口。ConcurrentHashMap中的containsKey方法如下:

...    public boolean containsKey(Object key) {        return get(key) != null;    }    public V get(Object key) {        Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;        int h = spread(key.hashCode());   // key not null        if ((tab = table) != null && (n = tab.length) > 0 &&            (e = tabAt(tab, (n - 1) & h)) != null) {            if ((eh = e.hash) == h) {                if ((ek = e.key) == key || (ek != null && key.equals(ek)))                    return e.val;            }            else if (eh < 0)                return (p = e.find(h, key)) != null ? p.val : null;            while ((e = e.next) != null) {                if (e.hash == h &&                    ((ek = e.key) == key || (ek != null && key.equals(ek))))                    return e.val;            }        }        return null;    }...

ConcurrentHashMap在调用containsKey方法时,会首取key的hashCode值,如果key为空,则会抛出NullPointerException。因此ConcurrentHashMap不能以null作为key

HashMap中的containsKey方法如下:

...    public boolean containsKey(Object key) {        return getNode(hash(key), key) != null;    }    static final int hash(Object key) {        int h;        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);    }        final Node<K,V> getNode(int hash, Object key) {        Node<K,V>[] tab; Node<K,V> first, e; int n; K k;        // key can be null        if ((tab = table) != null && (n = tab.length) > 0 &&            (first = tab[(n - 1) & hash]) != null) {            if (first.hash == hash && // always check first node                ((k = first.key) == key || (key != null && key.equals(k))))                return first;            if ((e = first.next) != null) {                if (first instanceof TreeNode)                    return ((TreeNode<K,V>)first).getTreeNode(hash, key);                do {                    if (e.hash == hash &&                        ((k = e.key) == key || (key != null && key.equals(k))))                        return e;                } while ((e = e.next) != null);            }        }        return null;    }    ...

HashMap中定义了hash方法,该方法入参为null时返回0。因此HashMap可以null作为key。HashMap是在put元素后分配空间,HashMap刚初始化时实际没有分配存储空间,当table为空时containsKey方法将直接返回null。

三、结论

ConcurrentHashMap不能以null作为key,key为null时将返回NullPointerException;HashMap可用null作为key,key为null时,返回hash值为0指向位置的值。

原创粉丝点击