天天看點

和阿裡面試官對線,多虧看完這篇HashSet源碼解析0 前言1 繼承體系2 屬性3 構造方法4 add(E e)5 remove6 總結

0 前言

HashSet 是一個沒有重複元素的集合.主要由 HashMap 實作,不保證元素順序,而允許 null 元素.非線程安全,如果需要安全請自行加鎖,或者使用 Collections.synchronizedSet包裝.最好在建立時完成這一操作,以防止對該 set 進行意外的不同步通路.

1 繼承體系

和阿裡面試官對線,多虧看完這篇HashSet源碼解析0 前言1 繼承體系2 屬性3 構造方法4 add(E e)5 remove6 總結

HashSet繼承自AbstractSet,并且實作了Set接口.HashSet的本質是一個"沒有重複元素"的集合,它是通過HashMap實作的。HashSet中含有一個"HashMap類型的成員變量"map,HashSet的操作函數,實際上都是通過map實作的.

和阿裡面試官對線,多虧看完這篇HashSet源碼解析0 前言1 繼承體系2 屬性3 構造方法4 add(E e)5 remove6 總結

2 屬性

  • HashSet 組合了 HashMap,把 HashMap 當作自己的一個局部變量
  • 和阿裡面試官對線,多虧看完這篇HashSet源碼解析0 前言1 繼承體系2 屬性3 構造方法4 add(E e)5 remove6 總結
  • 可以在基礎類方法的基礎上進行擴充,而且方法命名可以任意命名,無需和基礎類的方法名稱保持一緻.
  • 與後備Map中的對象關聯的虛拟 value
  • 和阿裡面試官對線,多虧看完這篇HashSet源碼解析0 前言1 繼承體系2 屬性3 構造方法4 add(E e)5 remove6 總結

3 構造方法

3.1 無參

  • 直接 new HashMap
  • 和阿裡面試官對線,多虧看完這篇HashSet源碼解析0 前言1 繼承體系2 屬性3 構造方法4 add(E e)5 remove6 總結

3.2 有參

  • 當有原始集合資料進行初始化的情況下
  • 和阿裡面試官對線,多虧看完這篇HashSet源碼解析0 前言1 繼承體系2 屬性3 構造方法4 add(E e)5 remove6 總結
  • 計算 HashMap 的容量:取括号中兩個數的最大值

(期望值 / 0.75+1,預設值 16)

若給定 HashMap 初始容量

< 16

 按照 HashMap 預設的 16 初始化

> 16

 按給定值初始化

HashMap 擴容門檻值:Map容量 * 0.75f,而此處的計算值正好比閥值大1,就不會立即擴容.

HashSet 的 API 都比較簡單,就是對 HashMap 的進行了簡單的包裝.我們簡單看幾個,

4 add(E e)

  • 直接使用 HashMap 的 put 方法并判斷
  • 和阿裡面試官對線,多虧看完這篇HashSet源碼解析0 前言1 繼承體系2 屬性3 構造方法4 add(E e)5 remove6 總結
  • 如果指定的元素尚不存在,則将其添加到該 set 中.更确切地說
  • 如果此元素集中不包含任何元素e2,使得

    (e==null ? e2==null : e.equals(e2))

    則将指定元素e添加到該元素集合中
  • 如果此集合已包含該元素,則調用将使該集合保持不變并傳回false

5 remove

  • 直接調用 HashMap 的 remove 方法并判斷
  • 和阿裡面試官對線,多虧看完這篇HashSet源碼解析0 前言1 繼承體系2 屬性3 構造方法4 add(E e)5 remove6 總結
  • 如果存在,則從此set中删除指定的元素.更确切地講,如果此set包含這樣的元素

(o==null ? e==null : o.equals(e))

則删除元素.

如果此集合包含該元素(或者說,如果此集合由于方法的調用而被更改),則傳回true.(一旦調用傳回,此集合将不包含該元素)

其他方法實作類似如此,不再贅述.

6 總結

HashSet 的實作給我們留下了一些最佳實踐

  • 組合有時比繼承更加适用
  • 注意封裝複雜邏輯,使對外接口充滿使用者體驗
  • 要對組合的其他資料結構十分了解,才能使代碼設計達到 1+1>2 奇效.

繼續閱讀