集合框架 - HashSet和HashMap實現原理

HashSet的實現


HashSet是基於HashMap實現的,只使用HashMap的key來實現各種特性,用PRESENT構造一個虛假的value。所以HashSet判斷兩個Key是否相等的機制和HansMap是一模一樣的:equals返回true並且和hashCode返回值相同。下面是HashSet的部分實現,看代碼:
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();

public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}
 
public boolean remove(Object o) {
    return map.remove(o)==PRESENT;
}
 
public boolean contains(Object o) {
    return map.containsKey(o);
}
 
public int size() {
    return map.size();
}

HashMap詳解


簡單來說,HashMap是一個數組加鏈表的存儲結構。添加的時候先將元素放到bucket當中,當key衝突的時候會通過鏈表鏈接起來。查找的時候先計算index去查找,第一次沒有命中就去遍歷鏈表,直到找到爲止。HaspMap是無序的,即遍歷結果的次序可能和插入的次序不同。要想遍歷的時候按插入次序輸出,請使用LinkedHashMap(鏈表結構)。


兩個重要的參數

在HashMap中有兩個很重要的參數,容量(Capacity)和負載因子(Load factor)。簡單的說,Capacity就是bucket的大小,Load factor就是bucket填滿程度的比例。如果對迭代性能要求很高的話不要把capacity設置過大,也不要把load factor設置過小。當bucket中的entries的數目大於capacity * load factor時就需要調整bucket的大小爲當前的2倍。

put方法的實現

put函數大致的思路爲:

  • 對key的hashCode()做hash,然後再計算index;

  • 如果沒碰撞直接放到bucket裏;

  • 如果碰撞了,以鏈表的形式存在bucket後面;

  • 如果碰撞導致鏈表過長(大於等於TREEIFY_THRESHOLD),就把鏈表轉換成紅黑樹;

  • 如果節點已經存在就替換old value(保證key的唯一性);

  • 如果bucket滿了(超過load factor*current capacity),就要resize。

get方法的實現

get的大致思路如下:

  1. bucket裏的第一個節點,直接命中;

  2. 如果有衝突,則通過key.equals(k)去查找對應的entry;

  3. 若爲樹,則在樹中通過key.equals(k)查找,時間複雜度爲O(logn);

  4. 若爲鏈表,則在鏈表中通過key.equals(k)查找,時間複雜度爲O(n)。

resize的實現

當put時,如果發現目前的bucket佔用程度已經超過了Load Factor所希望的比例,那麼就會發生resize。在resize的過程,簡單的說就是把bucket擴充爲2倍,之後重新計算index,把節點再放到新的bucket中。resize的註釋是這樣描述的:

Initializes or doubles table size. If null, allocates in accord with initial capacity target held in field threshold. Otherwise, because we are using power-of-two expansion, the elements from each bin must either stay at same index, or move with a power of two offset in the new table.

大致意思就是說,當超過限制的時候會resize,然而又因爲我們使用的是2次冪的擴展(指長度擴爲原來2倍),所以,元素的位置要麼是在原位置,要麼是在原位置再移動2次冪的位置。


更多詳情:Java HashMap的工作原理及實現



發佈了31 篇原創文章 · 獲贊 19 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章