HashMap原始碼分析(一)
阿新 • • 發佈:2021-01-03
原理簡介:
HashMap是利用雜湊表原理來儲存元素的一種集合。在JDK1.7中,HashMap底層是 陣列+連結串列 的, 在JDK1.8以後,HashMap底層改為 陣列+連結串列+紅黑樹 構成, 效率也變的更高效。
HashMap原始碼主要從幾個方面來看.
一 定義
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
繼承AbstractMap 實現Map介面, Cloneable介面 ,能複製和序列化.
二 成員變數 (原理中必須要用到的幾個重要引數)
private static final long serialVersionUID = 362498820763181265L; // UID 序列化用的.不解釋 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16, 初始化的陣列容量, 預設是16. 必須是2的倍數. static final int MAXIMUM_CAPACITY = 1 << 30; // 集合最大容量,1 << 30 為2的30次冪. 10億多. static final float DEFAULT_LOAD_FACTOR = 0.75f; // 擴充套件因子, 0.75, 當陣列中元素數量超過總容量的0.75倍(如預設容量16的0.75倍 12時,就會自動擴容) static final int TREEIFY_THRESHOLD = 8; // 樹化閾值(JDK1.8新增), 8 ,也就是當連結串列中元素個數大於等於8時, 連結串列會轉化為紅黑樹.對照下面的樹退化閾值記憶. static final int UNTREEIFY_THRESHOLD = 6; // 樹退化閾值(JDK1.8新增), 6, 當紅黑樹中元素個數少於等於6時, 紅黑樹會轉化為連結串列. 呼應前面的樹化閾值. static final int MIN_TREEIFY_CAPACITY = 64; // 當map中鍵值對總數量大於64時, 才會去判斷上面的樹化閾值.小於64時, 桶內元素太多隻會擴容,不會化成樹. //為了避免擴容和樹形化選擇衝突,這個值不能低於4*TREEIFY_THRESHOLD ,即32.
三 桶結構原始碼(從原始碼中可以看出,hash方式為key和value分別雜湊,結果再異或)
static class Node<K,V> implements Map.Entry<K,V> { final int hash; final K key; V value; Node<K,V> next; Node(int hash, K key, V value, Node<K,V> next) { this.hash = hash; this.key = key; this.value = value; this.next = next; } public final K getKey() { return key; } public final V getValue() { return value; } public final String toString() { return key + "=" + value; } public final int hashCode() { return Objects.hashCode(key) ^ Objects.hashCode(value); } public final V setValue(V newValue) { V oldValue = value; value = newValue; return oldValue; } public final boolean equals(Object o) { if (o == this) return true; if (o instanceof Map.Entry) { Map.Entry<?,?> e = (Map.Entry<?,?>)o; if (Objects.equals(key, e.getKey()) && Objects.equals(value, e.getValue())) return true; } return false; } }