当前位置:首页 > 科技  > 软件

高德面试:为什么Map不能插入Null?

来源: 责编: 时间:2024-06-06 17:43:21 82观看
导读在 Java 中,Map 是属于 java.util 包下的一个接口(interface),所以说“为什么 Map 不能插入 null?”这个问题本身问的不严谨。Map 部分类关系图如下:所以,这里面试官其实想问的是:为什么 ConcurrentHashMap 不能插入 null?1.Ha

MTK28资讯网——每日最新资讯28at.com

在 Java 中,Map 是属于 java.util 包下的一个接口(interface),所以说“为什么 Map 不能插入 null?”这个问题本身问的不严谨。Map 部分类关系图如下:MTK28资讯网——每日最新资讯28at.com

MTK28资讯网——每日最新资讯28at.com

所以,这里面试官其实想问的是:为什么 ConcurrentHashMap 不能插入 null?MTK28资讯网——每日最新资讯28at.com

1.HashMap和ConcurrentHashMap的区别

HashMap 和 ConcurrentHashMap 在对待 null 的态度上是不同的,在 Java 中,HashMap 是允许 key 和 value 值都为 null 的,如下代码所示:MTK28资讯网——每日最新资讯28at.com

HashMap<String, Object> map = new HashMap();map.put(null, null);if (map.containsKey(null)) {    System.out.println("存在 null");} else {    System.out.println("不存在 null");}

以上程序的执行结果如下:MTK28资讯网——每日最新资讯28at.com

存在 nullMTK28资讯网——每日最新资讯28at.com

从上述结果可以看出,HashMap 是允许  key 和 value 值都为 null 的。MTK28资讯网——每日最新资讯28at.com

但 ConcurrentHashMap 就不同了,它不但 key 不能为 null,而且 value 也不能为 null,如以下代码所示:MTK28资讯网——每日最新资讯28at.com

ConcurrentHashMap<String, String> concurrentHashMap = new ConcurrentHashMap();concurrentHashMap.put(null, "javacn.site");System.out.println(concurrentHashMap.get(null));

在运行以上程序时就会报错,如下图所示:MTK28资讯网——每日最新资讯28at.com

MTK28资讯网——每日最新资讯28at.com

当然,当你为 ConcurrentHashMap 的 value 值设置 null 时也会报错,如下代码所示:MTK28资讯网——每日最新资讯28at.com

String key = "www.avacn.site";ConcurrentHashMap<String, String> concurrentHashMap = new ConcurrentHashMap();concurrentHashMap.put(key, null);System.out.println(concurrentHashMap.get(key));

在运行以上程序时就会报错,如下图所示:MTK28资讯网——每日最新资讯28at.com

MTK28资讯网——每日最新资讯28at.com

因此,我们可以得出结论:MTK28资讯网——每日最新资讯28at.com

  • 在 HashMap 中,key 和 value 值都可以为 null。
  • 在 ConcurrentHashMap 中,key 或者是 value 值都不能为 null。

2.为什么不能插入null?

如果我们查看 ConcurrentHashMap 的源码,就能发现为什么 ConcurrentHashMap 不能插入 null 了,以下是 ConcurrentHashMap 添加元素时的部分核心源码:MTK28资讯网——每日最新资讯28at.com

// 添加 key 和 valuepublic V put(K key, V value) {    return putVal(key, value, false);}final V putVal(K key, V value, boolean onlyIfAbsent) {    // 如果 key 或 value 为 null 的话直接抛出空指针异常    if (key == null || value == null) throw new NullPointerException();    int hash = spread(key.hashCode());    int binCount = 0;    // 忽略其他代码......}

从上述 ConcurrentHashMap 添加元素的第一行源码就可以看出,当 key 或 value 为 null 时,会直接抛出空指针异常,这就是 ConcurrentHashMap 之所以不能插入 null 的根本原因了,因为源码就是这样设计的。MTK28资讯网——每日最新资讯28at.com

3.更深层次的原因

那么问题来了,为什么 ConcurrentHashMap 的实现源码中,不允许为 key 或者是 value 设置 null 呢?MTK28资讯网——每日最新资讯28at.com

这就要从 ConcurrentHashMap 的使用场景说起了,在 Java 中,ConcurrentHashMap 是用于并发环境中执行的线程安全的容器,而 HashMap 是用于单线程环境下执行的非线程安全的容器,而并发环境下的运行更复杂,如果我们允许 ConcurrentHashMap 的 key 或者是 value 为 null 的情况下,就会存在经典的“二义性问题”。MTK28资讯网——每日最新资讯28at.com

(1)什么是二义性问题?

所谓的二义性问题指的是代码或表达式存在多种理解或解释,导致程序的含义不明确或模糊。MTK28资讯网——每日最新资讯28at.com

以 ConcurrentHashMap 不允许为 null 的二义性问题来说,null 其实有以下两层含义:MTK28资讯网——每日最新资讯28at.com

  • 这个值本身设置的是 null,null 在这里表示的是一种具体的“null”值状态。
  • null 还表示“没有”的意思,因为没有设置,所以啥也没有。

所以,如果 ConcurrentHashMap 允许插入 null 值,那么就会存在二义性问题。MTK28资讯网——每日最新资讯28at.com

那就有同学会问了,为什么 HashMap 允许插入 null,它就不怕有二义性问题吗?MTK28资讯网——每日最新资讯28at.com

(2)可证伪的HashMap

HashMap 之所以不怕二义性问题的原因是,HashMap 的设计是给单线程使用的,而单线程下的二义性问题是能被证明真伪的,所以也就不存在二义性问题了(能被证明的问题就不是二义性问题)MTK28资讯网——每日最新资讯28at.com

例如,当我们给 HashMap 的 key 设置为 null 时,我们可以通过 hashMap.containsKey(key) 的方法来区分这个 null 值到底是存入的 null?还是压根不存在的 null?这样二义性问题就得到了解决,所以 HashMap 的二义性问题可被证明真伪,所以就不怕二义性问题,因此也就可以给 key 或者 value 设置 null 了。MTK28资讯网——每日最新资讯28at.com

(3)不可证伪的ConcurrentHashMap

而 ConcurrentHashMap 就不一样了,因为 ConcurrentHashMap 是设计在多线程下使用的,而多线程下的二义性问题是不能被证明真伪的,所以二义性问题是真实存在的。MTK28资讯网——每日最新资讯28at.com

因为在你在证明二义性问题的同时,可能会有另一个线程影响你的执行结果,所以它的二义性问题就一直存在。MTK28资讯网——每日最新资讯28at.com

例如,当 ConcurrentHashMap 未设置 key 为 null 时,会有这样一个场景,当一个线程 A 调用了 concurrentHashMap.containsKey(key),我们期望返回的结果是 false,但在我们调用 concurrentHashMap.containsKey(key) 之后,未返回结果之前,线程 B 又调用了 concurrentHashMap.put(key,null) 存入了 null 值,那么线程 A 最终返回的结果就是 true 了,这个结果和我们之前预想的 false 完全不一样,这就是不能被证伪的二义性问题。MTK28资讯网——每日最新资讯28at.com

所以说,多线程的执行比较复杂,在多线程下 null 的二义性问题是不能被证明真伪的(因为在一个线程执行验证时,可能会有另一个线程改动结果,造成结果不准确),所以 ConcurrentHashMap 为了避免这个二义性问题,所以就在源码中禁用了 null 值作为 key 或 value。MTK28资讯网——每日最新资讯28at.com

本文链接://www.dmpip.com//www.dmpip.com/showinfo-26-92476-0.html高德面试:为什么Map不能插入Null?

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 转转回收业务策略中心的实践

下一篇: 通过Spring Boot结合实时流媒体技术对考试过程进行实时监控

标签:
  • 热门焦点
  • 俄罗斯:将审查iPhone等外国公司设备 保数据安全

    俄罗斯:将审查iPhone等外国公司设备 保数据安全

    iPhone和特斯拉都属于在各自领域领头羊的品牌,推出的产品也也都是数一数二的,但对于一些国家而言,它们的产品可靠性和安全性还是在限制范围内。近日,俄罗斯联邦通信、信息技术
  • 天猫精灵Sound Pro体验:智能音箱没有音质?来听听我的

    天猫精灵Sound Pro体验:智能音箱没有音质?来听听我的

    这几年除了手机作为智能生活终端最主要的核心之外,第二个可以成为中心点的产品是什么?——是智能音箱。 手机在执行命令的时候有两种操作方式,手和智能语音助手,而智能音箱只
  • 7月安卓手机好评榜:三星S23Ultra好评率第一

    7月安卓手机好评榜:三星S23Ultra好评率第一

    性能榜和性价比榜之后,我们来看最后的安卓手机好评榜,数据来源安兔兔评测,收集时间2023年7月1日至7月31日,仅限国内市场。第一名:三星Galaxy S23 Ultra好评率:95.71%在即将迎来新
  • 如何通过Python线程池实现异步编程?

    如何通过Python线程池实现异步编程?

    线程池的概念和基本原理线程池是一种并发处理机制,它可以在程序启动时创建一组线程,并将它们置于等待任务的状态。当任务到达时,线程池中的某个线程会被唤醒并执行任务,执行完任
  • JavaScript学习 -AES加密算法

    JavaScript学习 -AES加密算法

    引言在当今数字化时代,前端应用程序扮演着重要角色,用户的敏感数据经常在前端进行加密和解密操作。然而,这样的操作在网络传输和存储中可能会受到恶意攻击的威胁。为了确保数据
  • 每天一道面试题-CPU伪共享

    每天一道面试题-CPU伪共享

    前言:了不起:又到了每天一到面试题的时候了!学弟,最近学习的怎么样啊 了不起学弟:最近学习的还不错,每天都在学习,每天都在进步! 了不起:那你最近学习的什么呢? 了不起学弟:最近在学习C
  • 本地生活这块肥肉,拼多多也想吃一口

    本地生活这块肥肉,拼多多也想吃一口

    出品/壹览商业 作者/李彦编辑/木鱼拼多多也看上本地生活这块蛋糕了。近期,拼多多在App首页&ldquo;充值中心&rdquo;入口上线了本机生活界面。壹览商业发现,该界面目前主要
  • 大厂卷向扁平化

    大厂卷向扁平化

    来源:新熵作者丨南枝 编辑丨月见大厂职级不香了。俗话说,兵无常势,水无常形,互联网企业调整职级体系并不稀奇。7月13日,淘宝天猫集团启动了近年来最大的人力制度改革,目前已形成一
  • 荣耀Magic4 至臻版 首创智慧隐私通话 强劲影音系统

    荣耀Magic4 至臻版 首创智慧隐私通话 强劲影音系统

    2022年第一季度临近尾声,在该季度内,许多品牌陆续发布自己的最新产品,让大家从全新的角度来了解当今的手机技术。手机是电子设备中,更新迭代十分迅速的一款产品,基
Top
Baidu
map