你知道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

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

相关推荐
2601_953988078 小时前
Ricon组态系统vs传统组态软件:为什么选择新一代Web组态平台
前端·后端·物联网·tcp/ip·数学建模·前端框架
chuan.bai8 小时前
Java RAG 实战(第 8 篇):Spring Boot RAG 查询 API
java·spring boot·贪心算法
FlyWIHTSKY8 小时前
idea中集成claude功能
java·ide·人工智能·intellij-idea·cloudera
IT_陈寒8 小时前
SpringBoot自动配置坑了我三天,原来漏了这个注解
前端·人工智能·后端
Java成神之路-8 小时前
Spring AI 统一结构化返回:ChatModel / ChatClient 两种实现方式
java·springaialibaba
Mr. zhihao8 小时前
深度解析:为什么Java序列化需要搭配ByteArrayOutputStream?IO装饰器模式的精妙设计
java·开发语言·装饰器模式
存在morning8 小时前
【Python 开发实践 一】Python vs Go vs Java 三门语言对比
java·python·golang
vx-程序开发9 小时前
springboot旅游推介平台---附源码24175
java·spring boot·python·spring cloud·eclipse·django·idea
AINative软件工程9 小时前
模型路由别写死在代码里:Policy-as-Code 才是 LLM 成本和质量的刹车片
后端
艾莉丝努力练剑9 小时前
【QT:解决问题】Qt5Core.dll:无法定位程序输入点
java·开发语言·qt·学习·面试