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

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

相关推荐
IT_10244 小时前
Spring Boot项目开发实战销售管理系统——系统设计!
大数据·spring boot·后端
Fireworkitte4 小时前
Apache POI 详解 - Java 操作 Excel/Word/PPT
java·apache·excel
weixin-a153003083164 小时前
【playwright篇】教程(十七)[html元素知识]
java·前端·html
DCTANT5 小时前
【原创】国产化适配-全量迁移MySQL数据到OpenGauss数据库
java·数据库·spring boot·mysql·opengauss
ai小鬼头5 小时前
AIStarter最新版怎么卸载AI项目?一键删除操作指南(附路径设置技巧)
前端·后端·github
Touper.5 小时前
SpringBoot -- 自动配置原理
java·spring boot·后端
黄雪超5 小时前
JVM——函数式语法糖:如何使用Function、Stream来编写函数式程序?
java·开发语言·jvm
ThetaarSofVenice5 小时前
对象的finalization机制Test
java·开发语言·jvm
一只叫煤球的猫5 小时前
普通程序员,从开发到管理岗,为什么我越升职越痛苦?
前端·后端·全栈
一只鹿鹿鹿5 小时前
信息化项目验收,软件工程评审和检查表单
大数据·人工智能·后端·智慧城市·软件工程