你知道ConcurrentHashMap 为什么 key 和 value 不能为 null,而HashMap的key和value都可以为null吗?

首先指明:HashMap 可以存储 null 的 key 和 value,但 null 作为键只能有一个,null 作为值可以有多个。这也是ConcurrentHashMap和HashMap的区别之一。

直接上源码:

HashMap#putVal()代码片段:

ini 复制代码
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {

ConcurrentHashMap#putVal()代码片段:

ini 复制代码
    final V putVal(K key, V value, boolean onlyIfAbsent) {
        if (key == null || value == null) throw new NullPointerException();
        int hash = spread(key.hashCode());
        int binCount = 0;
        for (Node<K,V>[] tab = table;;) {
            Node<K,V> f; int n, i, fh;
            if (tab == null || (n = tab.length) == 0)
                tab = initTable();
            else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
                if (casTabAt(tab, i, null,
                             new Node<K,V>(hash, key, value, null)))
                    break;                   // no lock when adding to empty bin
            }

直观上就能看出ConcurrentHashMap调用put(key, value)时,对key,value都进行判空处理,而HashMap并没有。这样设计的原因直接来看看作者的回答:

The main reason that nulls aren't allowed in ConcurrentMaps (ConcurrentHashMaps, ConcurrentSkipListMaps) is that ambiguities that may be just barely tolerable in non-concurrent maps can't be accommodated. The main one is that if map.get(key) returns null, you can't detect whether the key explicitly maps to null vs the key isn't mapped. In a non-concurrent map, you can check this via map.contains(key), but in a concurrent one, the map might have changed between calls.

翻译过来就是单线程情况下(HashMap)可以容忍歧义性,所谓的歧义看下面,但是多线程并发(ConcurrentHashMap)不能容忍歧义性,因为并发包的map,调用之间的map可能发生了变化,所以歧义性再加上多线程并发操作是不能容忍的,会加重设计的复杂度和曲折性

这就是作者这么设计的原因吧

ConcurrentHashMap 的 key 和 value 不能为 null 主要是为了避免模棱两可歧义性 :就拿#get(key)方法获取value值说说上面提到的歧义性:返回null有两种情况:

① map中没有这个key-value键值对,返回null

② map中有这个key-value键值对,但是value值为null,此时也返回null

这就上面所说的歧义,也就是二义性。

相关推荐
chuanauc2 分钟前
Kubernets K8s 学习
java·学习·kubernetes
一头生产的驴19 分钟前
java整合itext pdf实现自定义PDF文件格式导出
java·spring boot·pdf·itextpdf
YuTaoShao25 分钟前
【LeetCode 热题 100】73. 矩阵置零——(解法二)空间复杂度 O(1)
java·算法·leetcode·矩阵
zzywxc78729 分钟前
AI 正在深度重构软件开发的底层逻辑和全生命周期,从技术演进、流程重构和未来趋势三个维度进行系统性分析
java·大数据·开发语言·人工智能·spring
YuTaoShao3 小时前
【LeetCode 热题 100】56. 合并区间——排序+遍历
java·算法·leetcode·职场和发展
程序员张33 小时前
SpringBoot计时一次请求耗时
java·spring boot·后端
llwszx6 小时前
深入理解Java锁原理(一):偏向锁的设计原理与性能优化
java·spring··偏向锁
云泽野6 小时前
【Java|集合类】list遍历的6种方式
java·python·list
二进制person7 小时前
Java SE--方法的使用
java·开发语言·算法
小阳拱白菜8 小时前
java异常学习
java