最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java?中的HashMap的底層實(shí)現(xiàn)和元素添加流程

 更新時(shí)間:2022年05月09日 09:47:01   作者:??Java中文社群????  
這篇文章主要介紹了java?中的HashMap的底層實(shí)現(xiàn)和元素添加流程,HashMap?是使用頻率最高的數(shù)據(jù)類型之一,同時(shí)也是面試必問的問題之一,尤其是它的底層實(shí)現(xiàn)原理,下文更多詳細(xì)內(nèi)容,需要的小伙伴可以參考一下

前言:

HashMap 是使用頻率最高的數(shù)據(jù)類型之一,同時(shí)也是面試必問的問題之一,尤其是它的底層實(shí)現(xiàn)原理,既是常見的面試題又是理解 HashMap 的基石,所以重要程度不言而喻。

HashMap 底層實(shí)現(xiàn)

HashMap 在 JDK 1.7 和 JDK 1.8 的底層實(shí)現(xiàn)是不一樣的,在 JDK 1.7 中,HashMap 使用的是數(shù)組 + 鏈表實(shí)現(xiàn)的,而 JDK 1.8 中使用的是數(shù)組 + 鏈表或紅黑樹實(shí)現(xiàn)的。

HashMap 在 JDK 1.7 中的實(shí)現(xiàn)如下圖所示: 

 HashMap 在 JDK 1.8 中的實(shí)現(xiàn)如下圖所示: 

 我們本文重點(diǎn)來學(xué)習(xí)主流版本 JDK 1.8 中的 HashMap。HashMap 中每個(gè)元素稱之為一個(gè)哈希桶(bucket),

哈希桶包含的內(nèi)容有 4 個(gè):

  • hash 值
  • key
  • value
  • next(下一個(gè)節(jié)點(diǎn))

HashMap 插入流程

HashMap 元素新增的實(shí)現(xiàn)源碼如下(下文源碼都是基于主流版本 JDK 1.8):

public V put(K key, V value) {
    // 對 key 進(jìn)行哈希操作
    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;
    // 哈希表為空則創(chuàng)建表
    if ((tab = table) == null || (n = tab.length) == 0)
        n = (tab = resize()).length;
    // 根據(jù) key 的哈希值計(jì)算出要插入的數(shù)組索引 i
    if ((p = tab[i = (n - 1) & hash]) == null)
        // 如果 table[i] 等于 null,則直接插入
        tab[i] = newNode(hash, key, value, null);
    else {
        Node<K,V> e; K k;
        // 如果 key 已經(jīng)存在了,直接覆蓋 value
        if (p.hash == hash &&
            ((k = p.key) == key || (key != null && key.equals(k))))
            e = p;
        // 如果 key 不存在,判斷是否為紅黑樹
        else if (p instanceof TreeNode)
            // 紅黑樹直接插入鍵值對
            e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
        else {
            // 為鏈表結(jié)構(gòu),循環(huán)準(zhǔn)備插入
            for (int binCount = 0; ; ++binCount) {
                // 下一個(gè)元素為空時(shí)
                if ((e = p.next) == null) {
                    p.next = newNode(hash, key, value, null);
                    // 轉(zhuǎn)換為紅黑樹進(jìn)行處理
                    if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                        treeifyBin(tab, hash);
                    break;
                }
                //  key 已經(jīng)存在直接覆蓋 value
                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;
        }
    }
    ++modCount;
    // 超過最大容量,擴(kuò)容
    if (++size > threshold)
        resize();
    afterNodeInsertion(evict);
    return null;
}

上述的源碼都添加了相應(yīng)的代碼注釋,簡單來說 HashMap 的元素添加流程是,先將 key 值進(jìn)行 hash 得到哈希值,根據(jù)哈希值得到元素位置,判斷元素位置是否為空,如果為空直接插入,不為空判斷是否為紅黑樹,如果是紅黑樹則直接插入,否則判斷鏈表是否大于 8,且數(shù)組長度大于 64,如果滿足這兩個(gè)條件則把鏈表轉(zhuǎn)成紅黑樹,然后插入元素,如果不滿足這兩個(gè)條件中的任意一個(gè),則遍歷鏈表進(jìn)行插入,

它的執(zhí)行流程如下圖所示: 

為什么要將鏈表轉(zhuǎn)紅黑樹?

JDK 1.8 中引入了新的數(shù)據(jù)結(jié)構(gòu)紅黑樹來實(shí)現(xiàn) HashMap,主要是出于性能的考量。因?yàn)殒湵沓^一定長度之后查詢效率就會很低,它的時(shí)間復(fù)雜度是 O(n),而紅黑樹的時(shí)間復(fù)雜度是 O(logn),因此引入紅黑樹可以加快 HashMap 在數(shù)據(jù)量比較大的情況下的查詢效率。

哈希算法實(shí)現(xiàn)

HashMap 的哈希算法實(shí)現(xiàn)源碼如下:

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

其中,key.hashCode() 是 Java 中自帶的 hashCode() 方法,返回一個(gè) int 類型的散列值,后面 hashCode 再右移 16 位,正好是 32bit 的一半,與自己本身做異或操作(相同為 0,不同為 1),主要是為了混合哈希值的高位和低位,增加低位的隨機(jī)性,這樣就實(shí)現(xiàn)了 HashMap 的哈希算法。

總結(jié)

HashMap 在 JDK 1.7 時(shí),使用的是數(shù)組 + 鏈表實(shí)現(xiàn)的,而在 JDK 1.8 時(shí),使用的是數(shù)組 + 鏈表或紅黑樹的方式來實(shí)現(xiàn)的,JDK 1.8 之所以引入紅黑樹主要是出于性能方面的考慮。HashMap 在插入時(shí),會判斷當(dāng)前鏈表的長度是否大于 8 且數(shù)組的長度大于 64,如果滿足這兩個(gè)條件就會把鏈表轉(zhuǎn)成紅黑樹再進(jìn)行插入,否則就是遍歷鏈表插入。

到此這篇關(guān)于java 中的HashMap的底層實(shí)現(xiàn)和元素添加流程的文章就介紹到這了,更多相關(guān)Java中的HashMap內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中的同步非阻塞IO模型詳解

    Java中的同步非阻塞IO模型詳解

    這篇文章主要介紹了Java中的同步非阻塞IO模型詳解,同步非阻塞IO模型,我們能夠知道,用戶線程一直發(fā)送請求,內(nèi)核一直都能都夠返回 ,直到內(nèi)核完成準(zhǔn)備數(shù)據(jù)、數(shù)據(jù)拷貝的工作,并且返回成功的指示,在此過程中用戶線程不是阻塞的狀態(tài),需要的朋友可以參考下
    2024-01-01
  • Jenkins安裝以及郵件配置詳解

    Jenkins安裝以及郵件配置詳解

    這篇文章主要介紹了Jenkins安裝以及郵件配置相關(guān)問題,并通過圖文給大家做了詳細(xì)講解步驟,需要的朋友參考下吧。
    2017-12-12
  • MyBatis深入分析數(shù)據(jù)庫交互與關(guān)系映射

    MyBatis深入分析數(shù)據(jù)庫交互與關(guān)系映射

    這篇文章主要介紹了MyBatis中的數(shù)據(jù)庫交互與關(guān)系映射,MyBatis是一款優(yōu)秀的持久層框架,它支持定制化SQL、存儲過程以及高級映射,MyBatis避免了幾乎所有的JDBC代碼和手動設(shè)置參數(shù)以及獲取結(jié)果集,需要的朋友可以參考下
    2024-05-05
  • springboot多節(jié)點(diǎn)應(yīng)用里的雪花算法唯一性詳解

    springboot多節(jié)點(diǎn)應(yīng)用里的雪花算法唯一性詳解

    雪花算法在單節(jié)點(diǎn)下唯一,但在多副本Kubernetes環(huán)境中可能重復(fù),通過修改Pod名稱生成workId,解決了這個(gè)問題,同時(shí)避免了第三方組件和網(wǎng)絡(luò)請求,本文給大家介紹springboot多節(jié)點(diǎn)應(yīng)用里的雪花算法唯一性,感興趣的朋友一起看看吧
    2024-12-12
  • java中子類繼承父類,程序運(yùn)行順序的深入分析

    java中子類繼承父類,程序運(yùn)行順序的深入分析

    本篇文章是對java中子類繼承父類,程序運(yùn)行順序進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • Java?static關(guān)鍵字詳細(xì)解析

    Java?static關(guān)鍵字詳細(xì)解析

    這篇文章主要介紹了Java?static關(guān)鍵字詳細(xì)解析,java中的static關(guān)鍵字主要用于內(nèi)存管理,可以用在變量、方法、代碼塊和嵌套類中。更多相關(guān)介紹,需要的小伙伴可以參考一下
    2022-08-08
  • Java8中List轉(zhuǎn)換String字符串幾種方式

    Java8中List轉(zhuǎn)換String字符串幾種方式

    這篇文章主要給大家介紹了關(guān)于Java8中List轉(zhuǎn)換String字符串的幾種方式,在實(shí)際開發(fā)中經(jīng)常遇到List轉(zhuǎn)為String字符串的情況,文中給出了幾種方法的示例代碼,需要的朋友可以參考下
    2023-07-07
  • 關(guān)于Java中的try-with-resources語句

    關(guān)于Java中的try-with-resources語句

    這篇文章主要介紹了關(guān)于Java中的try-with-resources語句,try-with-resources是Java中的環(huán)繞語句之一,旨在減輕開發(fā)人員釋放try塊中使用的資源的義務(wù),需要的朋友可以參考下
    2023-05-05
  • 編寫android撥打電話apk應(yīng)用實(shí)例代碼

    編寫android撥打電話apk應(yīng)用實(shí)例代碼

    這篇文章主要介紹了編寫android撥打電話apk應(yīng)用實(shí)例代碼,十分的實(shí)用,這里分享給大家,有需要的小伙伴可以參考下
    2015-04-04
  • 基于ssm中dao接口@Param注解的用法

    基于ssm中dao接口@Param注解的用法

    這篇文章主要介紹了基于ssm中dao接口@Param注解的用法,具有很好的參考價(jià)值,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02

最新評論

阿瓦提县| 兰溪市| 界首市| 仙居县| 兴业县| 石台县| 盘锦市| SHOW| 昆明市| 广州市| 山东省| 资溪县| 新安县| 尼勒克县| 阿拉尔市| 蒙阴县| 宜宾县| 汕尾市| 隆化县| 含山县| 中宁县| 辽中县| 龙川县| 镇康县| 沈阳市| 枞阳县| 廉江市| 浦城县| 浪卡子县| 玉环县| 桦川县| 磴口县| 河东区| 台安县| 鄯善县| 泸西县| 罗山县| 本溪市| 姚安县| 射洪县| 黑河市|