java之map集合存放null值的問題
java map集合存放null值問題
今天接到阿里的電話面試提到了一個問題是關(guān)于HashTable、HashMap的區(qū)別
集合類 | key | value | super | 說明 |
HashTable | 不能為null | 不能為null | Dictionary | 線程安全 |
ConcurrentHashMap | 不能為null | 不能為null | AbstractMap | 線程局部安全 |
TreeMap | 不能為null | 可以為null | AbstractMap | 線程不安全 |
HashMap | 可以為null | 可以為null | AbstractMap | 線程不安全 |
以此為記~
java 集合能否加入null值
項目場景
劍指 Offer 09. 用兩個棧實現(xiàn)隊列
public int deleteHead() { while(s2.isEmpty()){ //注意這里,我直接判斷第二個??站图尤氲谝粋€棧中的元素,沒有判斷第一個棧是否為空(當(dāng)時想的是第一個棧為空不會加入元素或者拋出異常) s2.offerFirst(s1.pollFirst()); } if(s1.isEmpty()&&s2.isEmpty()){ return -1; } return s2.pollFirst(); }
問題描述
寫力扣題時出現(xiàn)了這個問題,原代碼在上面。
原因分析
嘗試輸出了下,發(fā)現(xiàn)總是返回空值,
1)認(rèn)為輸入棧(s1)為空會拋出異常,但是忘記了offer和poll針對異常不做處理,push和pop會拋出異常
2)跟著debug發(fā)現(xiàn)輸出棧(s2)元素永遠(yuǎn)不為空,因為加入了s1的null,這就有意思了,java中有的集合可以加入null,有的不可以,所以順便總結(jié)一下。
解決方案
public int deleteHead() { while(s1.isEmpty()&&s2.isEmpty()){ return -1; } if(s2.isEmpty()){ while(!s1.isEmpty()){ s2.offerFirst(s1.pollFirst()); } } return s2.pollFirst(); }
1.List
可以看到ArrayList可以存儲多個null,ArrayList底層是數(shù)組,添加null并未對他的數(shù)據(jù)結(jié)構(gòu)造成影響。LinkedList底層為雙向鏈表,node.value = null也沒有影響。
@Test public void testArrayList() { ArrayList<Integer> list = new ArrayList<>(); list.add(null); list.add(null); System.out.println(list.size());//2 } @Test public void testLinkedList() { LinkedList<Integer> list = new LinkedList<>(); list.add(null); list.add(null); System.out.println(list.size());//2 }
2.Set
Set底層是map,所以和map一樣
3.Map
關(guān)于Map,HashMap中最多只有一個key == null的節(jié)點,因為key相同時,后面的節(jié)點會替換之前相同key的節(jié)點,所以HashMap是可以添加key == null 的節(jié)點的,只不過只會存在一個put方法返回舊值。
TreeMap的put方法會調(diào)用compareTo方法,對象為null時,會報空指針錯。
@Test public void testHashMap() { HashMap<Integer, Integer> map = new HashMap<>(); map.put(null, null); map.put(null, null); System.out.println(map.size());//1 } @Test public void testTreeMap() { TreeMap<Integer, Integer> map = new TreeMap<>(); map.put(null, null); System.out.println(map.size());//NullPointerException }
TreeMap源碼
4.Vector
Vector 底層是數(shù)組,所以不會管你元素的內(nèi)容是什么,可以存儲多個null
@Test public void VectorTest(){ Vector box = new Vector(); box.add(null); box.add(null); Assert.assertEquals(2,box.size()); //ok } /** *此為Vector的add函數(shù) **/ public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; }
5.HashTable
HashTable底層為散列表,無論是key為null,還是value為null,都會報錯
@Test public void HashTableTest(){ Hashtable table = new Hashtable(); //table.put(new Object(),null); //Exception //table.put(null,new Object()); //Exception //table.put(null,null); //Exception Assert.assertEquals(1,table.size()); } //此為hashTable#put函數(shù)源碼 public synchronized V put(K key, V value) { // Make sure the value is not null if (value == null) { //value 需要判空,所以value不可為null throw new NullPointerException(); } // Makes sure the key is not already in the hashtable. Entry<?,?> tab[] = table; int hash = key.hashCode(); //key需要擁有實例去調(diào)用hashCode方法,所以也不能為空 int index = (hash & 0x7FFFFFFF) % tab.length; @SuppressWarnings("unchecked") Entry<K,V> entry = (Entry<K,V>)tab[index]; for(; entry != null ; entry = entry.next) { if ((entry.hash == hash) && entry.key.equals(key)) { V old = entry.value; entry.value = value; return old; } } addEntry(hash, key, value, index); return null; }
至于為什么hashtable鍵和值都設(shè)計成不能為null,??途W(wǎng)的一位大佬這樣說到:
6.ConcurrentHashMap
看上面那張圖
總結(jié)
結(jié)果:
- List都可以添加null元素
- HashMap可以有1個key為null的元素,TreeMap不能key為null的元素
- Set底層是Map,所以HashSet可以有1個null的元素,TreeSet不能有key為null的元素。
- -線程安全的類key和value都不能是null
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
maven如何動態(tài)統(tǒng)一修改版本號的方法步驟
這篇文章主要介紹了maven如何動態(tài)統(tǒng)一修改版本號的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12Java中Date與String相互轉(zhuǎn)換的方法
這篇文章主要為大家詳細(xì)介紹了Java中Date與String相互轉(zhuǎn)換方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-10-10SpringBoot中@Pattern注解對時間格式校驗方式
這篇文章主要介紹了SpringBoot中@Pattern注解對時間格式校驗方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09spring schedule配置多任務(wù)動態(tài)cron(增刪啟停)
這篇文章主要介紹了spring schedule配置多任務(wù)動態(tài)cron(增刪啟停),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03Java開發(fā)Spark應(yīng)用程序自定義PipeLineStage詳解
這篇文章主要為大家介紹了Java開發(fā)Spark應(yīng)用程序自定義PipeLineStage詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-02-02springboot讀取自定義配置文件時出現(xiàn)亂碼解決方案
這篇文章主要介紹了springboot讀取自定義配置文件時出現(xiàn)亂碼解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11ElasticSearch學(xué)習(xí)之多條件組合查詢驗證及示例分析
這篇文章主要為大家介紹了ElasticSearch 多條件組合查詢驗證及示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-02-02spring+mybatis實現(xiàn)圖書管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了spring+mybatis實現(xiàn)圖書管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-06-06