真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

循序漸進(jìn)分析源碼之HashMapput方法的示例分析

循序漸進(jìn)分析源碼之 HashMap put 方法的執(zhí)行流程(jdk 1.8 )的示例分析,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲。

鐵鋒網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、APP開(kāi)發(fā)、響應(yīng)式網(wǎng)站建設(shè)等網(wǎng)站項(xiàng)目制作,到程序開(kāi)發(fā),運(yùn)營(yíng)維護(hù)。成都創(chuàng)新互聯(lián)于2013年創(chuàng)立到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選成都創(chuàng)新互聯(lián)。

預(yù)備知識(shí)

注意:這里不會(huì)講紅黑樹(shù)是什么,以及如何具體實(shí)現(xiàn)。我們只需知道它長(zhǎng)什么樣子并了解它的好處即可。

為什么 在jdk1.8 中采用數(shù)組+鏈表/紅黑樹(shù)的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)數(shù)據(jù)?

當(dāng) Hash 沖突嚴(yán)重時(shí),在數(shù)組上的鏈表會(huì)越來(lái)越長(zhǎng),此時(shí)就會(huì)會(huì)降低查詢時(shí)的效率;時(shí)間復(fù)雜度為 O(N)。 引入紅黑樹(shù)之后查詢效率直接提高到了 O(logn)。

引入紅黑樹(shù)后,HashMap 內(nèi)部數(shù)據(jù)結(jié)構(gòu)長(zhǎng)什么樣子?

循序漸進(jìn)分析源碼之 HashMap put 方法的示例分析

什么時(shí)候會(huì)采用鏈表,什么時(shí)候用紅黑樹(shù)?

當(dāng)鏈表的大小大于預(yù)設(shè)的閾值(8)時(shí)就要轉(zhuǎn)換為紅黑樹(shù)

put 方法源碼(帶注釋)

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
               boolean evict) {
    Node[] tab; // 局部變量,指向容器
    Node p; // 局部變量
    int n, i;
    // 1. 如果 HashMap 沒(méi)有初始化,需要進(jìn)行初始化
    if ((tab = table) == null || (n = tab.length) == 0)
        n = (tab = resize()).length;
    // 2. 根據(jù)計(jì)算出的元素所在數(shù)組中的位置,并判斷目標(biāo)位置是否為空
    // 2.1 如果為空. new 一個(gè)新的 Node 放置在目標(biāo)位置
    if ((p = tab[i = (n - 1) & hash]) == null)
        tab[i] = newNode(hash, key, value, null);
    // 2.2 如果不為空, 再分情況討論
    else {
        Node e; 
        K k;
        // 2.2.1 如果目標(biāo)位置有值(有可能是紅黑樹(shù)的根節(jié)點(diǎn),也有可能是鏈表的表頭),就比較key 是否相同(相當(dāng)于提前判斷吧)
        if (p.hash == hash &&
            ((k = p.key) == key || (key != null && key.equals(k))))
            e = p;
        // 2.2.2 如果目標(biāo)位置放的是一個(gè)紅黑樹(shù),就按照紅黑樹(shù)的方式,寫(xiě)入數(shù)據(jù)
        else if (p instanceof TreeNode)
            e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value);
        // 2.2.3 如果目標(biāo)位置放置的是一個(gè)鏈表,就遍歷整個(gè)鏈表。
        else {
            for (int binCount = 0; ; ++binCount) {
            	// 如果當(dāng)前節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)為空,就 new 一個(gè)新的節(jié)點(diǎn),然后當(dāng)前節(jié)點(diǎn)指向這個(gè)新節(jié)點(diǎn)
                if ((e = p.next) == null) {
                    p.next = newNode(hash, key, value, null);
                    // 對(duì)這個(gè)增加了一個(gè)節(jié)點(diǎn)的鏈表進(jìn)行長(zhǎng)度判斷,如果長(zhǎng)度大于閥值,就將鏈表轉(zhuǎn)成紅黑樹(shù)
                    if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                        treeifyBin(tab, hash);
                    break;
                }
                // 如果當(dāng)前節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)不為空,就要判斷 key 是否相同,如果相同,就跳出循環(huán)。
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    break;
                p = e;
            }
        }
        // 對(duì) 2.2.1 和 2.2.2 和 2.2.3 進(jìn)行判斷。判斷成立表示要覆蓋原有位置的元素。
        if (e != null) { 
            V oldValue = e.value;
            if (!onlyIfAbsent || oldValue == null)
                e.value = value;
            afterNodeAccess(e);
            return oldValue;
        }
    }
    // 下面是擴(kuò)容代碼,暫時(shí)忽略
    ++modCount;
    if (++size > threshold)
        resize();
    afterNodeInsertion(evict);
    return null;
}

put 方法的流程圖

循序漸進(jìn)分析源碼之 HashMap put 方法的示例分析

看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對(duì)創(chuàng)新互聯(lián)的支持。


新聞標(biāo)題:循序漸進(jìn)分析源碼之HashMapput方法的示例分析
新聞來(lái)源:http://weahome.cn/article/jdeppi.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部