為什么ConcurrentHashMap的key value不能為null,map可以?
源碼
if (key == null || value == null) throw new NullPointerException();
二義性
假定ConcurrentHashMap也可以存放value為null的值。那不管是HashMap還是ConcurrentHashMap調(diào)用map.get(key)的時候,如果返回了null,那么這個null,
都有兩重含義:
1.這個key從來沒有在map中映射過。
2.這個key的value在設(shè)置的時候,就是null。
為什么map允許value=null
對于HashMap的正確使用場景是在單線程下使用。
在單線程中,當(dāng)我們得到的value是null的時候,我可以用hashMap.containsKey(key)方法來區(qū)分上面說的兩重含義。
所以當(dāng)map.get(key)返回的值是null,在HashMap中雖然存在二義性,但是結(jié)合containsKey方法可以避免二義性。
為什么ConcurrentHashMap不允許
ConcurrentHashMap的使用場景為多線程。
用反證法來推理,假設(shè)concurrentHashMap允許存放值為null的value。
這時有A、B兩個線程。
線程A調(diào)用concurrentHashMap.get(key)方法,返回為null,我們還是不知道這個null是沒有映射的null還是存的值就是null。
我們假設(shè)此時返回為null的真實情況就是因為這個key沒有在map里面映射過。那么我們可以用concurrentHashMap.containsKey(key)來驗證我們的假設(shè)是否成立,我們期望的結(jié)果是返回false。
但是在我們調(diào)用concurrentHashMap.get(key)方法之后,containsKey方法之前,有一個線程B執(zhí)行了concurrentHashMap.put(key,null)的操作。那么我們調(diào)用containsKey方法返回的就是true了。這就與我們的假設(shè)的真實情況不符合了。也就是上面說的二義性。
對于key不能為null
源碼就是這樣。。
補充:Hashtable/HashMap與key/value為null的關(guān)系
1、 HashMap計算key的hash值時調(diào)用單獨的方法,在該方法中會判斷key是否為null,如果是則返回0;而Hashtable中則直接調(diào)用key的hashCode()方法,因此如果key為null,則拋出空指針異常。
2、 HashMap將鍵值對添加進(jìn)數(shù)組時,不會主動判斷value是否為null;而Hashtable則首先判斷value是否為null。
3、以上原因主要是由于Hashtable繼承自Dictionary,而HashMap繼承自AbstractMap。
4、雖然ConcurrentHashMap也繼承自AbstractMap,但是其也過濾掉了key或value為null的鍵值對。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
SpringBoot整合Dubbo框架,實現(xiàn)RPC服務(wù)遠(yuǎn)程調(diào)用
Dubbo是一款高性能、輕量級的開源Java RPC框架,它提供了三大核心能力:面向接口的遠(yuǎn)程方法調(diào)用,智能容錯和負(fù)載均衡,以及服務(wù)自動注冊和發(fā)現(xiàn)。今天就來看下SpringBoot整合Dubbo框架的步驟2021-06-06Spring?boot集成easy?excel實現(xiàn)導(dǎo)入導(dǎo)出功能
這篇文章主要介紹了Spring?boot集成easy?excel實現(xiàn)導(dǎo)入導(dǎo)出操作,使用easyexcel,首先要引入easyexcel的maven依賴,具體的版本根據(jù)你的需求去設(shè)置,本文結(jié)合實例代碼講解的非常詳細(xì),需要的朋友可以參考下2024-05-05詳解使用spring aop實現(xiàn)業(yè)務(wù)層mysql 讀寫分離
本篇文章主要介紹了使用spring aop實現(xiàn)業(yè)務(wù)層mysql 讀寫分離,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-01-01Java concurrency集合之LinkedBlockingDeque_動力節(jié)點Java學(xué)院整理
LinkedBlockingDeque是雙向鏈表實現(xiàn)的雙向并發(fā)阻塞隊列。該阻塞隊列同時支持FIFO和FILO兩種操作方式,即可以從隊列的頭和尾同時操作(插入/刪除);并且,該阻塞隊列是支持線程安全。2017-06-06