public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, Cloneable, Serializable {
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; //默認的初始容量-必須是2的冪。
static final int MAXIMUM_CAPACITY = 1 << 30; //最大容量,如果較高的值是由任何帶有參數的構造函數隱式指定的。必須是2的冪<= 1<<30。
static final float DEFAULT_LOAD_FACTOR = 0.75f; //在構造函數中未指定時使用的負載因子。
static final int TREEIFY_THRESHOLD = 8; //樹的臨界值
static final int UNTREEIFY_THRESHOLD = 6; //在調整大小操作期間取消(分割)存儲庫的存儲計數閾值。應小於TREEIFY_THRESHOLD,並最多6個網格與收縮檢測下去除。
static final int MIN_TREEIFY_CAPACITY = 64; //最小的表容量,可爲容器進行樹狀排列。
transient Node<K, V>[] table; //表,在第一次使用時初始化,並根據需要調整大小。分配時,長度總是2的冪。
transient Set<Map.Entry<K, V>> entrySet; //保存緩存
transient int size; //這個映射中包含的鍵值映射的數量。
transient int modCount; //修改的次數
int threshold; //調整大小的下一個大小值(容量*負載因子)。
final float loadFactor; //哈希表的負載因子。
//在第一次請求該視圖時,每個字段都被初始化爲包含適當視圖的實例。視圖是無狀態的,因此沒有理由創建多個視圖。
transient volatile Set<K> keySet; (AbstractMap)
transient volatile Collection<V> values; (AbstractMap)
//基本哈希bin節點,用於大多數條目。(參見下面的TreeNode子類,以及LinkedHashMap中的條目子類)
static class Node<K, V> implements Map.Entry<K, V> {
final int hash; //哈希值
final K key; //鍵
V value; //值
Node<K, V> next;//下一個值
}
static final int hash(Object key){ //key的hashcode ^ hashCode >>> 16
int h;
return (key==null) ? 0 :(h = key.hashCode()) ^ (h >>> 16);
}
static final int tableSizeFor(int cap){ //該方法保證了容量的長度是2的n次冪
int n = cap - 1;
n |= n>>>1;
n |= n>>>2;
n |= n>>>4;
n |= n>>>8;
n |= n>>>16;
return (n<0) ? 1 : (n>=MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n+1;
}
final Node<K, V>[] resize() {
Node<K, V>[] oldTab = table;
int oldCap = (oldTab == null) ? 0 : oldTab.length;
int oldThr = threshold;
int newCap, newThr = 0; //新容量 與 新擴容閾值
if (oldCap > 0) { //如果容量大於0(這時候table不爲null了, oldCap爲16的n次冪)
if (oldCap >= MAXIMUM_CAPACITY) { //如果容量大於最大值(1 << 30)
threshold = Integer.MAX_VALUE; //取最大值
return oldTab;
} else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && oldCap >= DEFAULT_INITIAL_CAPACITY) { //擴容(原容量*2) 並且大於等於默認容量16
newThr = oldThr << 1; // 擴容閾值(原閾值*2) 12的n次冪
}
} else if (oldThr > 0) { // 初始容量設爲閾值
newCap = oldThr;
} else { // 零初始閾值表示使用默認值(第一次 put() 的時候 默認容量爲16 擴容閾值爲12)
newCap = DEFAULT_INITIAL_CAPACITY; // 16
newThr = (int) (DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY); // 16 * 0.75f = 12
}
if (newThr == 0) { //如果閾值爲0 設置閾值(新的容量*擴展因子0.75f)
float ft = (float) newCap * loadFactor;
newThr = (newCap < MAXIMUM_CAPACITY && ft < (float) MAXIMUM_CAPACITY ? (int) ft : Integer.MAX_VALUE);
}
threshold = newThr; //擴容閾值 = 新的擴容閾值
Node<K, V>[] newTab = (Node<K, V>[]) new Node[newCap]; //實例化新的表
table = newTab; //賦值給當前table
if (oldTab != null) { //第一次put除外 就不爲空
for (int j = 0; j < oldCap; ++j) { //
Node<K, V> e; //臨時使用
if ((e = oldTab[j]) != null) { //如果當前元素不爲空
oldTab[j] = null; //設置元素爲空
if (e.next == null) {
newTab[e.hash & (newCap - 1)] = e;
} else if (e instanceof TreeNode) {
((TreeNode<K, V>) e).split(this, newTab, j, oldCap);
} else { // preserve order
Node<K, V> loHead = null, loTail = null;
Node<K, V> hiHead = null, hiTail = null;
Node<K, V> next;
do {
next = e.next;
if ((e.hash & oldCap) == 0) {
if (loTail == null)
loHead = e;
else
loTail.next = e;
loTail = e;
} else {
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
if (loTail != null) {
loTail.next = null;
newTab[j] = loHead;
}
if (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}
}
}
}
}
return newTab;
}
}
Java HashMap 解析
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.