Java集合 --- HashMap

HashMap采用Entry數(shù)組來存儲key-value對,每一個鍵值對組成了一個Entry實體鹿响,Entry類實際上是一個單向的鏈表結(jié)構(gòu)羡微,它具有Next指針,可以連接下一個Entry實體惶我,依次來解決Hash沖突的問題妈倔,因為HashMap是按照Key的hash值來計算Entry在HashMap中存儲的位置的,如果hash值相同绸贡,而key內(nèi)容不相等盯蝴,那么就用鏈表來解決這種hash沖突毅哗。

put方法簡單解析

public V put(K key, V value) {
    //調(diào)用putVal()方法完成
    return putVal(hash(key), key, value, false, true);
}

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
               boolean evict) {
    Node<K,V>[] tab; Node<K,V> p; int n, i;
    //判斷table是否初始化,否則初始化操作
    if ((tab = table) == null || (n = tab.length) == 0)
        n = (tab = resize()).length;
    //計算存儲的索引位置捧挺,如果沒有元素虑绵,直接賦值
    if ((p = tab[i = (n - 1) & hash]) == null)
        tab[i] = newNode(hash, key, value, null);
    else {
        Node<K,V> e; K k;
        //節(jié)點(diǎn)若已經(jīng)存在,執(zhí)行賦值操作
        if (p.hash == hash &&
            ((k = p.key) == key || (key != null && key.equals(k))))
            e = p;
        //判斷鏈表是否是紅黑樹
        else if (p instanceof TreeNode)
            //紅黑樹對象操作
            e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
        else {
            //為鏈表闽烙,
            for (int binCount = 0; ; ++binCount) {
                if ((e = p.next) == null) {
                    p.next = newNode(hash, key, value, null);
                    //鏈表長度8翅睛,將鏈表轉(zhuǎn)化為紅黑樹存儲
                    if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                        treeifyBin(tab, hash);
                    break;
                }
                //key存在,直接覆蓋
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    break;
                p = e;
            }
        }
        if (e != null) { // existing mapping for key
            V oldValue = e.value;
            if (!onlyIfAbsent || oldValue == null)
                e.value = value;
            afterNodeAccess(e);
            return oldValue;
        }
    }
    //記錄修改次數(shù)
    ++modCount;
    //判斷是否需要擴(kuò)容
    if (++size > threshold)
        resize();
    //空操作
    afterNodeInsertion(evict);
    return null;
}

下面將這個過程總結(jié)一下:

如果當(dāng)前map中沒有數(shù)據(jù)黑竞,執(zhí)行resize方法
如果要插入的鍵值對要存放的位置上剛好沒有元素捕发,那么就把它封裝成Node對象,并放在這個位置上很魂。
如果發(fā)生碰撞爬骤,判斷node的類型是紅黑樹還是鏈表:
3.1 如果為紅黑樹,則將K-V對插在紅黑樹對應(yīng)的位置莫换。
3.2 如果為鏈表霞玄,遍歷鏈表:
 a.如果為鏈表最后一個node ,則將新的node節(jié)點(diǎn)插入到鏈表尾
 b.插入完,如果鏈表的node數(shù)量大于8拉岁,則將鏈表轉(zhuǎn)為紅黑樹的操作坷剧;如果當(dāng)前哈希表為空或數(shù)組長度小于64,會擴(kuò)容喊暖,否則轉(zhuǎn)化為紅黑樹惫企。轉(zhuǎn)化的過程:先遍歷鏈表 ,將鏈表的節(jié)點(diǎn)轉(zhuǎn)化為紅黑樹的節(jié)點(diǎn)陵叽;然后將鏈表轉(zhuǎn)化為紅黑樹狞尔。
c.遍歷鏈表時,如果key已存在巩掺,則直接bredk循環(huán)偏序。
判斷是否要擴(kuò)容
返回

總結(jié)
HashMap采用hash算法來決定Map中key的存儲,并通過hash算法來增加集合的大小胖替。hash表里可以存儲元素的位置稱為桶研儒,如果通過key計算hash值發(fā)生沖突時,那么將采用鏈表的形式独令,來存儲元素端朵。HashMap的擴(kuò)容操作是一項很耗時的任務(wù),所以如果能估算Map的容量燃箭,最好給它一個默認(rèn)初始值冲呢,避免進(jìn)行多次擴(kuò)容。HashMap的線程是不安全的招狸,多線程環(huán)境中推薦是ConcurrentHashMap敬拓。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末邻薯,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子恩尾,更是在濱河造成了極大的恐慌弛说,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翰意,死亡現(xiàn)場離奇詭異木人,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)冀偶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門醒第,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人进鸠,你說我怎么就攤上這事稠曼。” “怎么了客年?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵霞幅,是天一觀的道長。 經(jīng)常有香客問我量瓜,道長司恳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任绍傲,我火速辦了婚禮扔傅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘烫饼。我一直安慰自己猎塞,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布杠纵。 她就那樣靜靜地躺著荠耽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪淡诗。 梳的紋絲不亂的頭發(fā)上骇塘,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天,我揣著相機(jī)與錄音韩容,去河邊找鬼。 笑死唐瀑,一個胖子當(dāng)著我的面吹牛群凶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播哄辣,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼请梢,長吁一口氣:“原來是場噩夢啊……” “哼赠尾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起毅弧,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤气嫁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后够坐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寸宵,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年元咙,在試婚紗的時候發(fā)現(xiàn)自己被綠了梯影。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡庶香,死狀恐怖甲棍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情赶掖,我是刑警寧澤感猛,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站奢赂,受9級特大地震影響陪白,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜呈驶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一拷泽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧袖瞻,春花似錦司致、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至霉晕,卻和暖如春庭再,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背牺堰。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工拄轻, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人伟葫。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓恨搓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子斧抱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評論 2 348