ConcurrentHashMap 產生NullPointerException


今天測試在發給我一段報錯日志后,根據日志定位到從ConcurrentHashMap 的緩存中get的時候,ConcurrentHashMap的底層拋出了空指針,當時感覺很奇怪為什么在get的時候產生空指針了呢?

模擬代碼:

ConcurrentHashMap  concurrentHashMap = new ConcurrentHashMap();

........................................................

concurrentHashMap.get(傳入的參數);

這個地方出現空指針,難道是傳入的null 所以出現了空指針了,事實證明確實傳入了null,但是我記得hashmap 是可以傳入null 的呀? 為什么ConcurrentHashMap 卻不行呢?

相應的去驗證了一下,remove  方法發現也不能傳入null 進去。

一、異常分析

FATAL EXCEPTION: main
java.lang.NullPointerException
    at java.util.concurrent.ConcurrentHashMap.remove(ConcurrentHashMap.java:921)

本以為是並發異常,后發現不對,因為ConcurrentHashMap已經使用繼承自ReentrantLock的Segment,保證了線程安全,Java如果有這么大的bug肯定早修復了。看了下源碼

發現自己大意了,在獲取hashCode時NPE(hashMap不會,因為它會對null key做一次處理)。ConcurrentHashMap不接受null key和null value這個常識一時疏忽了,調用的地方確實有可能傳入null。這樣在remove前進行null判斷即可解決。

在問題解決后,想到hashMap和linkedhashMap都允許null key和null value,treeMap不允許null key,但允許null value,而ConcurrentHashMap既不允許null key也不允許null value,why?

二、not allow null key and value
stackoverflow並結合了源碼分析了一下
(1) treeMap不允許null key是因為compare會導致NPE, 可通過以下代碼實現null key支持

SortedMap<Integer, Integer> map = new TreeMap<Integer, Integer>(new Comparator<Integer>() {
 
                                    @Override
                                    public int compare(Integer arg0, Integer arg1) {
                                        if (arg0 == null) {
                                            if (arg1 == null) return 0;
                                            return -1;
                                        }
                                        if (arg1 == null) return 1;
                                        return arg0.compareTo(arg1);
                                    }
                                });

(2) ConcurrentHashMap不允許null key和null value,是因為ConcurrentHashMap的鎖機制
對於get(Object key)如果返回null,ConcurrentHashMap沒辦法判斷是key不存在還是value就是null。有人得問了那么hashmap呢, 為什么可以,hashmap我們可以通過下面代碼實現判斷


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM