Java ConcurrentHashMap vs HashMap和NullPointerException

Java ConcurrentHashMap vs HashMap和NullPointerException,java,hashmap,concurrenthashmap,Java,Hashmap,Concurrenthashmap,目前我正在使用ConcurrentHashMap,我非常熟悉HashMap,我预期会出现与HashMap类似的行为,但当我插入null键或值时,ConcurrentHashMap会抛出NullPointerException 我看到了它们的来源,ConcurrentHashMap的片段: ... public V put(K key, V value) { return putVal(key, value, false); } ... final V putVal(K key, V va

目前我正在使用
ConcurrentHashMap
,我非常熟悉
HashMap
,我预期会出现与
HashMap
类似的行为,但当我插入
null
键或值时,
ConcurrentHashMap
会抛出
NullPointerException

我看到了它们的来源,
ConcurrentHashMap
的片段:

...
public V put(K key, V value) {
    return putVal(key, value, false);
}
...
final V putVal(K key, V value, boolean onlyIfAbsent) {
    if (key == null || value == null) throw new NullPointerException();
    ....
...
public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}
...
final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
    Node<K,V>[] tab; Node<K,V> p; int n, i;
    // It Doesn't check null key or value.
    ....
以及
HashMap
的片段:

...
public V put(K key, V value) {
    return putVal(key, value, false);
}
...
final V putVal(K key, V value, boolean onlyIfAbsent) {
    if (key == null || value == null) throw new NullPointerException();
    ....
...
public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}
...
final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
    Node<K,V>[] tab; Node<K,V> p; int n, i;
    // It Doesn't check null key or value.
    ....
。。。
公共V输入(K键,V值){
返回putVal(散列(键)、键、值、false、true);
}
...
最终V putVal(整数散列、K键、V值、布尔值onlyFabSent、布尔值逐出){
节点[]选项卡;节点p;int n,i;
//它不检查null键或值。
....
为什么它们在使用
null
键或值时会如此不同?这对我来说没有意义。

从中可以看到:

这个类及其视图和迭代器实现了所有可选的 映射和迭代器接口的方法

与Hashtable类似,但与HashMap不同,该类不允许使用null 用作键或值

此类是Java集合框架的成员


您可以参考Doug Lea的评论:


ConcurrentMaps(ConcurrentHashMaps,ConcurrentSkipListMaps)中不允许使用空值的主要原因是无法容纳在非并发映射中几乎无法容忍的歧义。主要原因是如果map.get(key)返回null,您无法检测密钥是否显式映射为null,或者密钥是否未映射。在非并发映射中,您可以通过map.contains(key)检查这一点,但在并发调用中,映射可能在调用之间发生了更改。

与Hashtable类似,但与HashMap不同,此类不允许将null用作键或值。
我可以理解键的原因,但值的原因是什么??