回覆列表
-
1 # 三僡然
-
2 # 會點程式碼的大叔
找到這個問題答案最簡單的方法,就是看一下原始碼,也順便了解一下HashSet其他方面的知識。
開啟HashSet的原始碼,可以看到:
首先可以看到,HashSet的底層實現,是基於HashMap的。
private static final Object PRESENT = new Object();map = new HashMap<>();因為底層實現是HashMap,這也就理解了為什麼HashSet不允許重複。
另外,很容易就發現我們需要找的內容:PRESENT
private static final Object PRESENT = new Object();先看add()方法,可以發現插入到HashMap裡面的value是一個final的Object物件,而不是Null:
最後,我們在remove方法裡面,可以找到我們需要的答案:
由於HashSet的Remove實質就是HashMap的Remove,所以在看下HashMap的原始碼:
想象一下,如果HashSet中底層的value存null的話,那麼當map.remove(o)==null的時候,是沒有辦法知道這個null究竟代表了什麼。
透過原始碼分析,應該是為了區別remove時是否成功
每次將新鍵放入對映時,HashSet都不會新增新的Object。它確實使用了Object,但每次都使用相同的Object。該值在HashSetsource程式碼中命名為PRESENT。add方法在內部HashMap上呼叫put(key,PRESENT)。remove方法呼叫內部HashMap上的remove(key),但它必須返回一個布林值,指示該鍵是否存在。如果將null儲存為值,則HashSet需要先呼叫containsKey,然後刪除,以確定金鑰是否存在 - 額外的開銷。這裡,只有一個Object的記憶體開銷,這是非常小的。