HashMap 底層原理詳解

1. 核心數據結構

JDK 1.7 及之前數組 + 鏈表
JDK 1.8 及之后數組 + 鏈表/紅黑樹(鏈表長度 ≥8 時轉紅黑樹,≤6 時退化為鏈表)

// JDK 1.8 的 Node 定義(鏈表節點)
static class Node<K,V> implements Map.Entry<K,V> {final int hash;final K key;V value;Node<K,V> next; // 鏈表指針
}// TreeNode 定義(紅黑樹節點)
static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {TreeNode<K,V> parent;  // 父節點TreeNode<K,V> left;    // 左子樹TreeNode<K,V> right;   // 右子樹TreeNode<K,V> prev;    // 前驅節點boolean red;           // 顏色標識
}

2. 哈希函數設計

作用:將 Key 映射到數組索引,盡可能減少哈希沖突。
JDK 1.8 的優化

static final int hash(Object key) {int h;// 高16位與低16位異或,提升散列性return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

索引計算
index = (table.length - 1) & hash

  • 長度取模優化:哈希表容量為 2 的冪次時,(n-1) & hash?等效于?hash % n,但位運算更快。


3. put() 方法流程
  1. 計算哈希值:調用?hash(key)

  2. 初始化或擴容:若數組為空,調用?resize()?初始化(默認容量 16,負載因子 0.75)。

  3. 定位桶位置index = (n-1) & hash

  4. 處理哈希沖突

    • 鏈表插入

      • JDK 1.7:頭插法(易導致死循環)。

      • JDK 1.8:尾插法(解決死循環問題)。

    • 樹化處理:若鏈表長度 ≥8 且數組長度 ≥64,鏈表轉紅黑樹。

  5. 覆蓋或新增節點

    • Key 已存在:覆蓋 Value,返回舊值。

    • Key 不存在:插入新節點,返回 null。

  6. 擴容檢查:若元素總數 > 閾值(容量 × 負載因子),觸發?resize()


4. 擴容機制(resize())

觸發條件:元素數量超過閾值(容量 × 負載因子,默認 0.75)。
擴容流程

  1. 新容量計算:舊容量 × 2(保證容量始終為 2 的冪次)。

  2. 遷移元素

    • JDK 1.7:遍歷舊數組,重新哈希每個元素到新數組(頭插法)。

    • JDK 1.8:優化遷移邏輯,鏈表元素拆分為高位鏈和低位鏈(無需重新哈希):

      • 低位鏈:原索引位置

      • 高位鏈:原索引位置 + 舊容量

優化原理
由于新容量是舊容量的 2 倍,(newCap - 1) & hash?的結果僅取決于哈希值的第?log2(oldCap)?位是否為 1:

  • 若為 0 → 索引不變(低位鏈)。

  • 若為 1 → 索引 = 原索引 + 舊容量(高位鏈)。


5. 紅黑樹優化

樹化條件

  • 鏈表長度 ≥?TREEIFY_THRESHOLD(默認 8)。

  • 數組長度 ≥?MIN_TREEIFY_CAPACITY(默認 64)。

退化條件

  • 紅黑樹節點數 ≤?UNTREEIFY_THRESHOLD(默認 6)。

優勢

  • 鏈表查詢復雜度 O(n),紅黑樹查詢復雜度 O(logn),顯著減少哈希沖突時的性能損耗。


6. 關鍵參數與默認值
參數默認值說明
DEFAULT_INITIAL_CAPACITY16默認初始容量
DEFAULT_LOAD_FACTOR0.75負載因子(擴容閾值 = 容量 × 負載因子)
TREEIFY_THRESHOLD8鏈表轉紅黑樹的閾值
UNTREEIFY_THRESHOLD6紅黑樹退化為鏈表的閾值
MIN_TREEIFY_CAPACITY64允許樹化的最小數組長度

7. 性能優化建議
  • 初始化容量:預估元素數量,避免頻繁擴容(如預計存 1000 元素,初始容量設為 2048)。

  • 重寫 hashCode() 和 equals():確保 Key 對象的哈希分布均勻且相等性判斷準確。

  • 避免高頻修改:多線程場景使用?ConcurrentHashMap


總結

  • 核心結構:數組 + 鏈表/紅黑樹,動態擴容優化性能。

  • 哈希設計:高位異或、位運算取模、紅黑樹優化沖突。

  • 線程安全:非線程安全,需使用替代方案。

  • 實戰技巧:合理初始化容量、重寫哈希方法、避免并發操作。


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/76788.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/76788.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/76788.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用MySQL時出現 Ignoring query to other database 錯誤

Ignoring query to other database 錯誤 當在遠程連接軟件中輸入MySQL命令出現該錯誤 導致錯誤原因是&#xff1a;登錄mysql時賬戶名沒有加上u 如果出現該錯誤&#xff0c;退出mysql&#xff0c;重新輸入正確格式進入即可&#xff01;

哈爾濱工業大學:大模型時代的具身智能

大家好&#xff0c;我是櫻木。 機器人在工業領域&#xff0c;已經逐漸成熟。具身容易&#xff0c;智能難。 機器人-》智能機器人&#xff0c;需要自主能力&#xff0c;加上通用能力。 智能機器人-》人類&#xff0c;這個階段就太有想象空間了。而最受關注的-類人機器人。 如何…

Javascript代碼壓縮混淆工具terser詳解

原始的JavaScript代碼在正式的服務器上,如果沒有進行壓縮,混淆,不僅加載速度比較慢,而且還存在安全和性能問題. 因此現在需要進行壓縮,混淆處理. 處理方案簡單描述一下: 1. 使用 terser 工具進行 安裝 terser工具: # npm 安裝 npm install terser --save-dev# 或使用 yarn 安…

Java String 常用方法詳解

目錄 一、獲取字符串信息(一)獲取字符串長度(二)獲取指定索引處的字符(三)獲取子字符串二、字符串比較(一)比較字符串內容(二)忽略大小寫比較三、字符串轉換(一)轉換為大寫(二)轉換為小寫四、字符串查找(一)查找子字符串的位置(二)從指定位置開始查找五、字符…

Linux驅動開發練習案例

1 開發目標 1.1 架構圖 操作系統&#xff1a;基于Linux5.10.10源碼和STM32MP157開發板&#xff0c;完成tf-a(FSBL)、u-boot(SSBL)、uImage、dtbs的裁剪&#xff1b; 驅動層&#xff1a;為每個外設配置DTS并且單獨封裝外設驅動模塊。其中電壓ADC測試&#xff0c;采用linux內核…

leetcode-代碼隨想錄-哈希表-贖金信

題目 題目鏈接&#xff1a;383. 贖金信 - 力扣&#xff08;LeetCode&#xff09; 給你兩個字符串&#xff1a;ransomNote 和 magazine &#xff0c;判斷 ransomNote 能不能由 magazine 里面的字符構成。 如果可以&#xff0c;返回 true &#xff1b;否則返回 false 。 maga…

精品可編輯PPT | “新基建”在數字化智慧高速公路中的支撐應用方案智慧建筑智慧交通解決方案施工行業解決方案

本文詳細闡述了“新基建”在數字化智慧高速公路中的支撐應用方案&#xff0c;從政策背景出發&#xff0c;指出國家在交通領域的一系列發展規劃和指導意見&#xff0c;強調了智慧交通建設的重要性。分析了當前高速公路存在的問題&#xff0c;如基礎感知設施不足、協同水平低、服…

C語言求3到100之間的素數

一、代碼展示 二、運行結果 三、感悟思考 注意: 這個題思路他是一個試除法的一個思路 先進入一個for循環 遍歷3到100之間的數字 第二個for循環則是 判斷他不是素數 那么就直接退出 這里用break 是素數就打印出來 在第一個for循環內 第二個for循環外

英語—四級CET4考試—蒙猜篇—匹配題

蒙猜方法一 匹配題的做題&#xff1a; 方法一&#xff1a; 首先&#xff0c;什么都不想&#xff0c;把問題中ing形式的&#xff0c;大寫字母的&#xff0c;人名&#xff0c;地名&#xff0c;最后幾個依次框起來。 然后&#xff0c;比如46題&#xff0c;口里默念meaningful lif…

股票日數據使用_未復權日數據生成前復權日周月季年數據

目錄 前置&#xff1a; 準備 代碼&#xff1a;數據庫交互部分 代碼&#xff1a;生成前復權 日、周、月、季、年數據 前置&#xff1a; 1 未復權日數據獲取&#xff0c;請查看 https://blog.csdn.net/m0_37967652/article/details/146435589 數據庫使用PostgreSQL。更新日…

系統與網絡安全------Windows系統安全(6)

資料整理于網絡資料、書本資料、AI&#xff0c;僅供個人學習參考。 共享文件夾 發布共享文件夾 Windows共享概述 微軟公司推出的網絡文件/打印機服務系統 可以將一臺主機的資源發布給其他主機共有 共享訪問的優點 方便、快捷相比光盤 U盤不易受文件大小限制 可以實現訪問…

BN 層的作用, 為什么有這個作用?

BN 層&#xff08;Batch Normalization&#xff09;——這是深度神經網絡中非常重要的一環&#xff0c;它大大改善了網絡的訓練速度、穩定性和收斂效果。 &#x1f9e0; 一句話理解 BN 層的作用&#xff1a; Batch Normalization&#xff08;批歸一化&#xff09;通過標準化每一…

判斷HiveQL語句為ALTER TABLE語句的識別函數

寫一個C#字符串解析程序代碼&#xff0c;邏輯是從前到后一個一個讀取字符&#xff0c;遇到匹配空格、Tab和換行符就繼續讀取下一個字符&#xff0c;遇到大寫或小寫的字符a&#xff0c;就讀取后一個字符并匹配是否為大寫或小寫的字符l&#xff0c;以此類推&#xff0c;匹配任意字…

基于編程的運輸設備管理系統設計(vue+springboot+ssm+mysql8.x)

基于編程的運輸設備管理系統設計&#xff08;vuespringbootssmmysql8.x&#xff09; 運輸設備信息管理系統是一個全面的設備管理平臺&#xff0c;旨在優化設備管理流程&#xff0c;提高運輸效率。系統提供登錄入口&#xff0c;確保只有授權用戶可以訪問。個人中心讓用戶可以查…

6.1 python加載win32或者C#的dll的方法

python很方便的可以加載win32的方法以及C#編寫的dll中的方法或者變量&#xff0c;大致過程如下。 一.python加載win32的方法&#xff0c;使用win32api 1.安裝庫win32api pip install win32api 2.加載所需的win32函數并且調用 import win32api win32api.MessageBox(0,"…

前端精度計算:Decimal.js 基本用法與詳解

一、Decimal.js 簡介 decimal.js 是一個用于任意精度算術運算的 JavaScript 庫&#xff0c;它可以完美解決浮點數計算中的精度丟失問題。 官方API文檔&#xff1a;Decimal.js 特性&#xff1a; 任意精度計算&#xff1a;支持大數、小數的高精度運算。 鏈式調用&#xff1a;…

SQL Server 數據庫實驗報告

??????? 1.1 實驗題目&#xff1a;索引和數據完整性的使用 1.2 實驗目的&#xff1a; &#xff08;1&#xff09;掌握SQL Server的資源管理器界面應用&#xff1b; &#xff08;2&#xff09;掌握索引的使用&#xff1b; &#xff08;3&#xff09;掌握數據完整性的…

AI繪畫中的LoRa是什么?

Lora是一個多義詞&#xff0c;根據不同的上下文可以指代多種事物。以下將詳細介紹幾種主要的含義&#xff1a; LoRa技術 LoRa&#xff08;Long Range Radio&#xff09;是一種低功耗廣域網&#xff08;LPWAN&#xff09;無線通信技術&#xff0c;以其遠距離、低功耗和低成本的特…

哈希表(Hashtable)核心知識點詳解

1. 基本概念 定義&#xff1a;通過鍵&#xff08;Key&#xff09;直接訪問值&#xff08;Value&#xff09;的數據結構&#xff0c;基于哈希函數將鍵映射到存儲位置。 核心操作&#xff1a; put(key, value)&#xff1a;插入鍵值對 get(key)&#xff1a;獲取鍵對應的值 remo…

數據流和重定向

1、數據流 不管正確或錯誤的數據都是默認輸出到屏幕上&#xff0c;所以屏幕是混亂的。所以就需要用數據流重定向將這兩 條數據分開。數據流重定向可以將標準輸出和標準錯誤輸出分別傳送到其他的文件或設備去 標準輸入&#xff08;standard input&#xff0c;簡稱stdin&#xff…