HashSet 源碼分析【面試+工作】

前言

在工作中,經常有這樣的需求,需要判斷某個ID是否在某個組的管理之下等,就需要查詢該組下的ID放到一個集合中,且集合中元素不能有重複,之後判斷該集合是否包含我們的目標ID;這時,我們可以使用 HashSet 來存放我們的ID,HashSet可以自動的幫助我們去重,比如HashSet<String> set = new HashSet<>(list) 等。接下來看下 HashSet 的內部是怎麼實現的。

HashSet的特點

從 HashSet 的 Javadoc 的說明中,可以得到以下信息:

1. HashSet 底層是使用 HashMap 來保存元素的

2.它不保證集合中存放元素的順序,即是無序的,且這種順序可能會隨着時間的推移還會改變

3.允許 null 值,且只有一個

4.HashSet 不是線程安全的,底層的 HashMap 不是線程安全的,它自然就不是啦,可以使用 Collections.synchronizedSet(new HashSet()) 來創建線程安全的 HashSet

5.集合中的元素不會重複

類圖

先來看看 HashSet 的一個類圖

從類圖中,可以看到, HashSet 繼承了 AbstractSet 抽象類, 而 AbstractSet 又繼承了 AbstractCollection 抽象類,此外,HashSet 還實現了 Set 接口等。

AbstractSet 抽象類主要實現了兩個方法 equals 和 hashcode 方法,因爲 HashSet 中沒有重複元素,就是根據這兩個方法來進行判斷的:

Set 接口,它是一個頂層接口,主要定義了一些公共的方法,如 add, isEmpty, size, remove, contains 等一些方法;HashSet, SortedSet,TreeSet 都實現了該接口。

源碼分析

接下來看下它的內部實現,它內部使用 HashMap 來存放元素,它的所有方法基本上都是調用 HashMap 的方法來實現的,相等於對HashMap包裝了一層。

從上面聲明可看到,HashSet 底層是使用 HashMap 來存放元素的,且 HashMap 中所有元素的 value 都是同一個 Object 對象,且它被 final 修飾。

接下來看下它的方法實現:

以上就是 HashSet 源碼的全部實現了,看着很簡單,但是要知道 HashMap 的實現過程纔會清楚。

HashSet 如何保證元素的不重複

接下來,看下 HashSet 的 add 方法,看下它是如何保證添加的元素不重複的

之後來看下 HashMap 的 put 方法:

put 方法會調用 putVal 方法進行添加元素,來看下 putVal 方法的實現:

所以,在向 HashSet 添加元素的時候,如果要添加元素的 hashcode 已存在,且 equals 相等,則會替換掉舊的值。

以上就是 HashSet 的實現。看起來很簡單,但是前提是得知道 HashMap 的實現。

總結

HashSet的特點

1. HashSet 底層是使用 HashMap 來保存元素的

2.它不保證集合中存放元素的順序,即是無序的,且這種順序可能會隨着時間的推移還會改變

3.允許 null 值,且只有一個

4.HashSet 不是線程安全的,底層的 HashMap 不是線程安全的,它自然就不是啦,可以使用 Collections.synchronizedSet(new HashSet()) 來創建線程安全的 HashSet

5.集合中的元素不會重複

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章