成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

高德面試:為什么Map不能插入Null?

開發 前端
在多線程下 null 的二義性問題是不能被證明真偽的(因為在一個線程執行驗證時,可能會有另一個線程改動結果,造成結果不準確),所以 ConcurrentHashMap 為了避免這個二義性問題,所以就在源碼中禁用了 null 值作為 key 或 value。

在 Java 中,Map 是屬于 java.util 包下的一個接口(interface),所以說“為什么 Map 不能插入 null?”這個問題本身問的不嚴謹。Map 部分類關系圖如下:

所以,這里面試官其實想問的是:為什么 ConcurrentHashMap 不能插入 null?

1.HashMap和ConcurrentHashMap的區別

HashMap 和 ConcurrentHashMap 在對待 null 的態度上是不同的,在 Java 中,HashMap 是允許 key 和 value 值都為 null 的,如下代碼所示:

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

以上程序的執行結果如下:

存在 null

從上述結果可以看出,HashMap 是允許  key 和 value 值都為 null 的。

但 ConcurrentHashMap 就不同了,它不但 key 不能為 null,而且 value 也不能為 null,如以下代碼所示:

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

在運行以上程序時就會報錯,如下圖所示:

當然,當你為 ConcurrentHashMap 的 value 值設置 null 時也會報錯,如下代碼所示:

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

在運行以上程序時就會報錯,如下圖所示:

因此,我們可以得出結論:

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

2.為什么不能插入null?

如果我們查看 ConcurrentHashMap 的源碼,就能發現為什么 ConcurrentHashMap 不能插入 null 了,以下是 ConcurrentHashMap 添加元素時的部分核心源碼:

// 添加 key 和 value
public 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 的根本原因了,因為源碼就是這樣設計的。

3.更深層次的原因

那么問題來了,為什么 ConcurrentHashMap 的實現源碼中,不允許為 key 或者是 value 設置 null 呢?

這就要從 ConcurrentHashMap 的使用場景說起了,在 Java 中,ConcurrentHashMap 是用于并發環境中執行的線程安全的容器,而 HashMap 是用于單線程環境下執行的非線程安全的容器,而并發環境下的運行更復雜,如果我們允許 ConcurrentHashMap 的 key 或者是 value 為 null 的情況下,就會存在經典的“二義性問題”。

(1)什么是二義性問題?

所謂的二義性問題指的是代碼或表達式存在多種理解或解釋,導致程序的含義不明確或模糊。

以 ConcurrentHashMap 不允許為 null 的二義性問題來說,null 其實有以下兩層含義:

  • 這個值本身設置的是 null,null 在這里表示的是一種具體的“null”值狀態。
  • null 還表示“沒有”的意思,因為沒有設置,所以啥也沒有。

所以,如果 ConcurrentHashMap 允許插入 null 值,那么就會存在二義性問題。

那就有同學會問了,為什么 HashMap 允許插入 null,它就不怕有二義性問題嗎?

(2)可證偽的HashMap

HashMap 之所以不怕二義性問題的原因是,HashMap 的設計是給單線程使用的,而單線程下的二義性問題是能被證明真偽的,所以也就不存在二義性問題了(能被證明的問題就不是二義性問題)

例如,當我們給 HashMap 的 key 設置為 null 時,我們可以通過 hashMap.containsKey(key) 的方法來區分這個 null 值到底是存入的 null?還是壓根不存在的 null?這樣二義性問題就得到了解決,所以 HashMap 的二義性問題可被證明真偽,所以就不怕二義性問題,因此也就可以給 key 或者 value 設置 null 了。

(3)不可證偽的ConcurrentHashMap

而 ConcurrentHashMap 就不一樣了,因為 ConcurrentHashMap 是設計在多線程下使用的,而多線程下的二義性問題是不能被證明真偽的,所以二義性問題是真實存在的。

因為在你在證明二義性問題的同時,可能會有另一個線程影響你的執行結果,所以它的二義性問題就一直存在。

例如,當 ConcurrentHashMap 未設置 key 為 null 時,會有這樣一個場景,當一個線程 A 調用了 concurrentHashMap.containsKey(key),我們期望返回的結果是 false,但在我們調用 concurrentHashMap.containsKey(key) 之后,未返回結果之前,線程 B 又調用了 concurrentHashMap.put(key,null) 存入了 null 值,那么線程 A 最終返回的結果就是 true 了,這個結果和我們之前預想的 false 完全不一樣,這就是不能被證偽的二義性問題。

所以說,多線程的執行比較復雜,在多線程下 null 的二義性問題是不能被證明真偽的(因為在一個線程執行驗證時,可能會有另一個線程改動結果,造成結果不準確),所以 ConcurrentHashMap 為了避免這個二義性問題,所以就在源碼中禁用了 null 值作為 key 或 value。

責任編輯:姜華 來源: Java中文社群
相關推薦

2022-01-27 07:02:52

JavaHashMap單線程

2022-05-08 18:18:40

JDKValueHashMap

2010-08-12 10:54:26

惠普

2022-05-18 08:25:59

MySQLutf8字符集數據庫

2023-07-03 08:15:46

MySQLInnoDB

2023-08-22 20:43:09

HashMap單線程null

2022-05-22 21:23:10

前端監控系統

2012-12-18 11:55:38

2021-07-30 06:49:40

SSD內存CPU

2025-02-24 16:00:00

JavaScripMap開發

2021-08-05 12:41:57

高并發性能CAS

2022-02-15 07:03:04

start 源碼run線程

2012-07-24 10:17:33

甲骨文

2023-12-08 08:40:16

函數

2013-10-29 10:24:31

程序員漫畫

2023-09-14 13:23:42

Llama-2模型參數

2022-07-27 07:36:01

TCP可靠性

2023-08-29 07:46:08

Redis數據ReHash

2025-06-04 02:55:00

MySQLNULL類型

2021-12-28 09:50:18

Redis單線程高并發
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 黄色片大全在线观看 | 国产一区二区精品自拍 | 国产精品久久久99 | 午夜视频在线观看视频 | 国产精品视频导航 | 日韩精品久久久 | 亚洲精彩视频在线观看 | 黄色av一区 | 国产一区二区精品在线观看 | 久久免费香蕉视频 | 精品久久久久一区二区国产 | 精品久久久久久久久久 | 91精品中文字幕一区二区三区 | 99精品在线免费观看 | 午夜网| 97超在线视频 | 国产精品一区二区久久久久 | 天堂在线91 | 色婷婷国产精品综合在线观看 | 日韩在线视频一区 | 亚洲成人免费视频 | 日韩综合| 精品视频一区二区三区在线观看 | 欧美 日韩 中文 | 日韩成人免费 | 亚洲一在线 | 亚洲 欧美 在线 一区 | 国产精品一区二区三区四区 | 国产亚洲精品久久19p | 国产精品日韩欧美一区二区 | 中文字幕人成乱码在线观看 | 狠狠爱免费视频 | 91影视| 在线观看电影av | 无人区国产成人久久三区 | 欧日韩不卡在线视频 | 精品久久国产 | 日韩中文电影 | 美日韩免费视频 | 欧美一区免费 | 欧美一区二区三区在线观看 |