Java HashMap 解析

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;
    }
}

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