HashMap分析

首先從構(gòu)造方法說起旁蔼,

初始化有兩個(gè)參數(shù)
initialCapacity 代表初始容量,實(shí)際容量為大于initialCapacity的2的冪次數(shù)
之后會初始化一個(gè)長度為initialCapacity的數(shù)組彼乌,姑且把數(shù)組中每個(gè)元素定義為一個(gè)桶铐殃。默認(rèn)桶內(nèi)個(gè)數(shù)為0 。隨著桶中個(gè)數(shù)的增加佳励,當(dāng)平均每個(gè)桶的元素個(gè)數(shù)大于loadFactor時(shí)休里,則觸發(fā)重構(gòu)蛆挫。

   public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY) {
            initialCapacity = MAXIMUM_CAPACITY;
        } else if (initialCapacity < DEFAULT_INITIAL_CAPACITY) {
            initialCapacity = DEFAULT_INITIAL_CAPACITY;
        }

        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);
        // Android-Note: We always use the default load factor of 0.75f.

        // This might appear wrong but it's just awkward design. We always call
        // inflateTable() when table == EMPTY_TABLE. That method will take "threshold"
        // to mean "capacity" and then replace it with the real threshold (i.e, multiplied with
        // the load factor).
        threshold = initialCapacity;
        init();
    }

HashMap里存放的是一個(gè)特殊的entity,格式如下

 static class HashMapEntry<K,V> implements Map.Entry<K,V> {
        final K key;
        V value;
        HashMapEntry<K,V> next;
        int hash;

        /**
         * Creates new entry.
         */
        HashMapEntry(int h, K k, V v, HashMapEntry<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();
        }

        /**
         * This method is invoked whenever the value in an entry is
         * overwritten by an invocation of put(k,v) for a key k that's already
         * in the HashMap.
         */
        void recordAccess(HashMap<K,V> m) {
        }

        /**
         * This method is invoked whenever the entry is
         * removed from the table.
         */
        void recordRemoval(HashMap<K,V> m) {
        }
    }

既然是HashMap那肯定跟Hash有關(guān)份帐。每次添加元素時(shí)璃吧,根據(jù)key的hash值計(jì)算出一個(gè)hashint,之后根據(jù)hashing%桶的個(gè)數(shù)獲取一個(gè)index废境,再根據(jù)這個(gè)index吧元素放到對應(yīng)的桶里畜挨。如果桶里有舊對象則讓新對象指向舊對象。如果key為null則放在第0個(gè)桶里

public V put(K key, V value) {
        if (table == EMPTY_TABLE) {
            inflateTable(threshold);
        }
        if (key == null)
            return putForNullKey(value);
        int hash = sun.misc.Hashing.singleWordWangJenkinsHash(key);
        int i = indexFor(hash, table.length);
        for (HashMapEntry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }

get方法也是類似根據(jù)key確定具體哪個(gè)桶里再遍歷鏈表比對key值獲取元素

 final Entry<K,V> getEntry(Object key) {
        if (size == 0) {
            return null;
        }

        int hash = (key == null) ? 0 : sun.misc.Hashing.singleWordWangJenkinsHash(key);
        for (HashMapEntry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash &&
                ((k = e.key) == key || (key != null && key.equals(k))))
                return e;
        }
        return null;
    }

當(dāng)總對象個(gè)數(shù)超過預(yù)定閾值觸發(fā)resize 桶的個(gè)數(shù)翻倍

 void resize(int newCapacity) {
        HashMapEntry[] oldTable = table;
        int oldCapacity = oldTable.length;
        if (oldCapacity == MAXIMUM_CAPACITY) {
            threshold = Integer.MAX_VALUE;
            return;
        }

        HashMapEntry[] newTable = new HashMapEntry[newCapacity];
        transfer(newTable);
        table = newTable;
        threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
    }

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末噩凹,一起剝皮案震驚了整個(gè)濱河市巴元,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌驮宴,老刑警劉巖逮刨,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異堵泽,居然都是意外死亡修己,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門迎罗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來睬愤,“玉大人,你說我怎么就攤上這事纹安∮热瑁” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵厢岂,是天一觀的道長光督。 經(jīng)常有香客問我,道長塔粒,這世上最難降的妖魔是什么结借? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮卒茬,結(jié)果婚禮上船老,老公的妹妹穿的比我還像新娘。我一直安慰自己扬虚,他們只是感情好努隙,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著辜昵,像睡著了一般荸镊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天躬存,我揣著相機(jī)與錄音张惹,去河邊找鬼。 笑死岭洲,一個(gè)胖子當(dāng)著我的面吹牛宛逗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播盾剩,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼雷激,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了告私?” 一聲冷哼從身側(cè)響起屎暇,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎驻粟,沒想到半個(gè)月后根悼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蜀撑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年挤巡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片酷麦。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡矿卑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出贴铜,到底是詐尸還是另有隱情粪摘,我是刑警寧澤瀑晒,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布绍坝,位于F島的核電站,受9級特大地震影響苔悦,放射性物質(zhì)發(fā)生泄漏轩褐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一玖详、第九天 我趴在偏房一處隱蔽的房頂上張望把介。 院中可真熱鬧,春花似錦蟋座、人聲如沸拗踢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽巢墅。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間君纫,已是汗流浹背驯遇。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蓄髓,地道東北人叉庐。 一個(gè)月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像会喝,于是被迫代替她去往敵國和親陡叠。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容