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

Java中的HashMap實(shí)現(xiàn)原理深入理解

 更新時(shí)間:2025年12月11日 09:33:45   作者:im_winter185  
HashMap是一種非常常見和實(shí)用的數(shù)據(jù)結(jié)構(gòu),它被廣泛應(yīng)用于Java編程中,這篇文章主要介紹了Java中HashMap實(shí)現(xiàn)原理的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下

一、前言

在 Java 開發(fā)中,HashMap 是我們最常用的集合類之一。無(wú)論是緩存、配置存儲(chǔ),還是數(shù)據(jù)傳輸,HashMap 都扮演著重要角色。但你是否真正了解它的底層實(shí)現(xiàn)?為什么它查找這么快?什么時(shí)候會(huì)退化成鏈表?JDK1.8 之后又有哪些優(yōu)化?

本文將帶你深入理解 HashMap 的實(shí)現(xiàn)原理,幫助你從“會(huì)用”到“懂原理”。

二、HashMap 的基本結(jié)構(gòu)

1. 底層數(shù)據(jù)結(jié)構(gòu)(JDK 1.8 之前 vs 之后)

版本數(shù)據(jù)結(jié)構(gòu)
JDK 1.7數(shù)組 + 鏈表
JDK 1.8數(shù)組 + 鏈表 + 紅黑樹

解釋:

  • 數(shù)組HashMap 的主干是一個(gè) Node<K,V>[] table,每個(gè)元素是一個(gè)桶(bucket)。

  • 鏈表:當(dāng)發(fā)生哈希沖突時(shí),多個(gè)鍵值對(duì)會(huì)以鏈表形式存儲(chǔ)在同一個(gè)桶中。

  • 紅黑樹:當(dāng)鏈表長(zhǎng)度超過(guò) 8 且數(shù)組長(zhǎng)度大于 64 時(shí),鏈表會(huì)轉(zhuǎn)為紅黑樹,提升查詢效率。

三、核心源碼解析

1. 構(gòu)造函數(shù)與初始容量

public HashMap(int initialCapacity, float loadFactor) {
    this.loadFactor = loadFactor;
    this.threshold = tableSizeFor(initialCapacity);
}
  • initialCapacity:初始容量,必須是 2 的冪。

  • loadFactor:負(fù)載因子,默認(rèn)是 0.75,用于控制擴(kuò)容時(shí)機(jī)。

2. put 方法流程

public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

步驟如下:

  1. 計(jì)算 key 的 hash 值(hash(key)

  2. 定位桶位置((n - 1) & hash

  3. 如果桶為空,直接插入

  4. 如果桶不為空,遍歷鏈表或紅黑樹

  5. 如果 key 已存在,覆蓋 value

  6. 如果插入后長(zhǎng)度超過(guò)閾值,觸發(fā)擴(kuò)容或樹化

3. 哈希函數(shù)設(shè)計(jì)

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

目的: 減少哈希沖突,讓高位也參與運(yùn)算,提升分布均勻性。

四、擴(kuò)容機(jī)制(resize)

當(dāng)元素個(gè)數(shù)超過(guò) threshold = capacity * loadFactor 時(shí),會(huì)觸發(fā)擴(kuò)容:

  • 容量翻倍(newCap = oldCap << 1

  • 重新計(jì)算每個(gè)元素的位置(要么在原位置,要么在原位置 + oldCap)

優(yōu)化點(diǎn): JDK 1.8 中不需要重新計(jì)算 hash,只需看新增的那一位是 0 還是 1。

五、線程安全問(wèn)題

?? HashMap 是線程不安全的!

問(wèn)題表現(xiàn):

  • 多線程 put 可能導(dǎo)致鏈表成環(huán)(JDK 1.7)

  • 數(shù)據(jù)丟失、覆蓋等問(wèn)題

解決方案:

方式說(shuō)明
Collections.synchronizedMap()包裝器,性能差
ConcurrentHashMap推薦,分段鎖/CAS 實(shí)現(xiàn),線程安全且高效

六、面試高頻問(wèn)題總結(jié)

問(wèn)題簡(jiǎn)答
HashMap 的底層結(jié)構(gòu)?數(shù)組 + 鏈表 + 紅黑樹(JDK 1.8)
為什么容量必須是 2 的冪?位運(yùn)算效率高,hash & (n-1) 替代取模
什么時(shí)候轉(zhuǎn)紅黑樹?鏈表長(zhǎng)度 > 8 且數(shù)組長(zhǎng)度 > 64
為什么加載因子是 0.75?平衡空間與時(shí)間效率
如何線程安全地使用 Map?使用 ConcurrentHashMap

七、總結(jié)思維導(dǎo)圖(文字版)

HashMap
├── 結(jié)構(gòu):數(shù)組 + 鏈表 + 紅黑樹
├── 核心方法:put、get、resize、hash
├── 優(yōu)化:樹化、擴(kuò)容、hash 散列
├── 線程安全:ConcurrentHashMap
└── 面試點(diǎn):容量、負(fù)載因子、沖突處理、樹化條件

八、附錄:手寫一個(gè)簡(jiǎn)易 HashMap(練習(xí))

public class MyHashMap<K, V> {
    private Node<K, V>[] table;
    private int size;

    static class Node<K, V> {
        final int hash;
        final K key;
        V value;
        Node<K, V> next;

        Node(int hash, K key, V value, Node<K, V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }
    }

    public void put(K key, V value) {
        // 簡(jiǎn)化版,省略擴(kuò)容、樹化等邏輯
    }

    public V get(K key) {
        // 簡(jiǎn)化版
        return null;
    }
}

九、結(jié)語(yǔ)

理解 HashMap 的底層實(shí)現(xiàn),不僅能幫助你在面試中脫穎而出,更能在實(shí)際開發(fā)中避免踩坑。希望本文能為你打下堅(jiān)實(shí)的基礎(chǔ)。

如果你覺得這篇文章對(duì)你有幫助,歡迎點(diǎn)贊、收藏、評(píng)論!
后續(xù)我還會(huì)更新《ConcurrentHashMap 源碼解析》《Java 集合框架全景圖》等內(nèi)容,記得關(guān)注我哦!

十、參考資料

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

相關(guān)文章

  • Java中for循環(huán)內(nèi)修改集合的常見陷阱與最佳實(shí)踐

    Java中for循環(huán)內(nèi)修改集合的常見陷阱與最佳實(shí)踐

    在Java編程中,for循環(huán)是遍歷集合(如List、Set)的常用方式,本文主要介紹了Java在for循環(huán)內(nèi)修改集合的常見陷阱與最佳實(shí)踐,希望對(duì)大家有所幫助
    2025-06-06
  • springboot hazelcast緩存中間件的實(shí)例代碼

    springboot hazelcast緩存中間件的實(shí)例代碼

    這篇文章主要介紹了springboot hazelcast緩存中間件的實(shí)例代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-08-08
  • SpringBoot常用注解,thymeleaf,數(shù)據(jù)提交的實(shí)現(xiàn)

    SpringBoot常用注解,thymeleaf,數(shù)據(jù)提交的實(shí)現(xiàn)

    SpringBoot簡(jiǎn)化了微服務(wù)配置,提供快速啟動(dòng)和內(nèi)嵌容器化web項(xiàng)目,常用注解包括@Component、@RestController等,Thymeleaf為前端頁(yè)面渲染提供支持,數(shù)據(jù)提交時(shí)需使用@RequestBody注解
    2026-01-01
  • 詳解springboot整合mongodb

    詳解springboot整合mongodb

    本篇文章主要介紹了詳解springboot整合mongodb,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05
  • 并發(fā)編程之Java內(nèi)存模型鎖的內(nèi)存語(yǔ)義

    并發(fā)編程之Java內(nèi)存模型鎖的內(nèi)存語(yǔ)義

    這篇文章主要介紹了并發(fā)編程之Java內(nèi)存模型鎖的內(nèi)存語(yǔ)義,鎖的作用是讓臨界區(qū)互斥執(zhí)行,本文只要圍繞鎖的內(nèi)存語(yǔ)義展開全文內(nèi)容,需要的小伙伴可以參考一下
    2021-11-11
  • Java 運(yùn)算符詳情

    Java 運(yùn)算符詳情

    這篇文章主要介紹了Java 運(yùn)算符,Java 中的運(yùn)算符與 C 語(yǔ)言基本一致。下面文章就圍繞Java 中的運(yùn)算符的相關(guān)資料展開內(nèi)容,需要的朋友可以參考一下
    2021-11-11
  • Spring?Bean后處理器詳細(xì)介紹

    Spring?Bean后處理器詳細(xì)介紹

    Bean后置處理器允許在調(diào)用初始化方法前后對(duì)Bean進(jìn)行額外的處理??梢栽?Spring容器通過(guò)插入一個(gè)或多個(gè)BeanPostProcessor的實(shí)現(xiàn)來(lái)完成實(shí)例化,配置和初始化一個(gè)?bean?之后實(shí)現(xiàn)一些自定義邏輯回調(diào)方法
    2023-01-01
  • springboot配置redis過(guò)程詳解

    springboot配置redis過(guò)程詳解

    這篇文章主要介紹了springboot配置redis過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • JVM類加載器之ClassLoader的使用詳解

    JVM類加載器之ClassLoader的使用詳解

    類加載器負(fù)責(zé)讀取Java字節(jié)代碼,并轉(zhuǎn)換成java.lang.Class類的一個(gè)實(shí)例的代碼模塊。本文主要和大家聊聊JVM類加載器ClassLoader的使用,需要的可以了解一下
    2022-10-10
  • Java輕松掌握面向?qū)ο蟮娜筇匦苑庋b與繼承和多態(tài)

    Java輕松掌握面向?qū)ο蟮娜筇匦苑庋b與繼承和多態(tài)

    本文主要講述的是面向?qū)ο蟮娜筇匦裕悍庋b,繼承,多態(tài),內(nèi)容含括從封裝到繼承再到多態(tài)的所有重點(diǎn)內(nèi)容以及使用細(xì)節(jié)和注意事項(xiàng),內(nèi)容有點(diǎn)長(zhǎng),請(qǐng)大家耐心看完
    2022-05-05

最新評(píng)論

潞西市| 海安县| 乡城县| 扶风县| 洪泽县| 阿图什市| 伽师县| 临泽县| 佳木斯市| 金山区| 琼中| 石台县| 洪泽县| 兴业县| 郴州市| 凉城县| 南雄市| 衡南县| 临沭县| 长阳| 新宁县| 中牟县| 诸暨市| 南宁市| 台东县| 禹城市| 阿城市| 双江| 班戈县| 大足县| 定南县| 龙海市| 桓仁| 临邑县| 昌江| 安阳市| 辉南县| 杭锦后旗| 酒泉市| 宁武县| 滨州市|