1. 程式人生 > >java HashMap類,底層自學自看 筆記(實時更新)

java HashMap類,底層自學自看 筆記(實時更新)

提示:本文章是基於jdk1.7,對於一些常見類底層學習的公開筆記,學藝不精,發現錯誤請評論提出。

一:實現的介面,繼承的類
繼承1:AbstractMap:是一個抽象類,他實現了Map介面。對Map介面的一些方法進行了實現。
2:Map<K,V>:是一個介面,規範map集合需要實現的方法
3:Cloneable:克隆介面,無任何方法引數,但卻實現了一個隱藏機制,無需呼叫構造器就可以建立物件的克隆機制。
4:Serializable:序列化
二:擁有的屬性


1

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; 

注:預設初始化容量屬性,意味著HashMap的預設初始化容量為16


2

static final int MAXIMUM_CAPACITY = 1 << 30;

注:最大容量:1 073 741 824


3

static final float DEFAULT_LOAD_FACTOR = 0.75f;

注:儲存因子具體值。儲存因子越大,對系統空間利用率越高,但越容易因為hash衝突,反之亦然。因此取了一箇中間值。


4

static final Entry<?,?>[] EMPTY_TABLE = {};
transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;

注:當新增等操作會用到,日後附帶程式碼說明,jdk標明的註釋,依舊解釋不清晰


5

transient int size;
int threshold;

注:長度,一個可以被序列化,一個不可以,後者是hashmap空間的長度,前者則是資料的長度。


6

final float loadFactor;//儲存因子

7

transient int modCount;

注:改值記錄了這個物件被操作的次數。即使map執行了clear方法,你個數值也不會被清零。假如克隆這個物件而新生成的物件,那麼新物件的這個屬性會是0;


8

static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;
 譯:可替換的程式碼值。也就是map裡連結串列的最大個數。

9

//內部類  沒有太高深的邏輯,底層也進入到了c語言,所以就做個簡單的分析
//儲存VM啟動後無法初始化的值。
private static class Holder {

        static final int ALTERNATIVE_HASHING_THRESHOLD;
	
        static {
            String altThreshold = java.security.AccessController.doPrivileged(
                new sun.security.action.GetPropertyAction(
                    "jdk.map.althashing.threshold"));
			//初始化的時候int預設為0,altThreshold也是0
			
            int threshold;
            try {
                threshold = (null != altThreshold)
                        ? Integer.parseInt(altThreshold)
                        : ALTERNATIVE_HASHING_THRESHOLD_DEFAULT;
			//顯然doPrivileged方法並不能保證一定會讀出來這個0的資料
                // disable alternative hashing if -1
                if (threshold == -1) {
                    threshold = Integer.MAX_VALUE;
                }

                if (threshold < 0) {
                    throw new IllegalArgumentException("value must be positive integer.");
                }
            } catch(IllegalArgumentException failed) {
                throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
            }

            ALTERNATIVE_HASHING_THRESHOLD = threshold;
        }
    }

注:那麼這個內部類的意義是什麼?其實 沒什麼高深的東西,就類似讀取配置檔案,初始化這個工具屬性。當長度發生改變時或者克隆都會用到。具體初始化了什麼還真不知道


10
我決定把這個內部類提前,因為這個比較重要,不先寫出來梳理的不順暢

//HashMap的核心這個表明了HashMap的儲存方式
static class Entry<K,V> implements Map.Entry<K,V> {
        final K key;
        V value;
        Entry<K,V> next;
        int hash;
        //所說的連結串列,不過是一個大腦虛擬的,方便理解的一種形式
        Entry(int h, K k, V v, Entry<K,V> n) {
            value = v;
            next = n;
            key = k;
            hash = h;
        }

        public final K getKey() {
            return key;
        }

        public final V getValue() {
            return value;
        }

        public final V setValue(V newValue) {
            V oldValue = value;
            value = newValue;
            return oldValue;
        }

        public final boolean equals(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry e = (Map.Entry)o;
            Object k1 = getKey();
            Object k2 = e.getKey();
            if (k1 == k2 || (k1 != null && k1.equals(k2))) {
                Object v1 = getValue();
                Object v2 = e.getValue();
                if (v1 == v2 || (v1 != null && v1.equals(v2)))
                    return true;
            }
            return false;
        }

        public final int hashCode() {
            return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());
        }

        public final String toString() {
            return getKey() + "=" + getValue();
        }
        void recordAccess(HashMap<K,V> m) {
        }
        void recordRemoval(HashMap<K,V> m) {
        }
    }

注:這雖然是核心,但卻沒什麼特殊的東西,沒有什麼高深的邏輯和技術。
當執行put方法是,其實就是在陣列的下一個索引上增加一個這個物件,next就是儲存的下一個這個物件。
具體的實現會慢慢以展現程式碼梳理。


2018年11月14日10:00:00,第一次更新。邊工作邊看底層,更新速度不會很快
2018年11月15日15:19:39,第二次更新