Java集合框架深度解析:HashMap、HashSet、TreeMap、TreeSet與哈希表原理詳解

一、核心數據結構總覽

1. 核心類繼承體系

graph TDMap接口 --> HashMapMap接口 --> TreeMapSet接口 --> HashSetSet接口 --> TreeSetHashMap --> LinkedHashMapHashSet --> LinkedHashSetTreeMap --> NavigableMapTreeSet --> NavigableSet

2. 核心特性對比表

特性HashMapTreeMapHashSetTreeSet
底層實現數組+鏈表/紅黑樹紅黑樹HashMap包裝TreeMap包裝
元素順序無序自然順序/自定義無序自然順序/自定義
插入/刪除/查找時間O(1)平均O(log n)O(1)平均O(log n)
線程安全非線程安全非線程安全非線程安全非線程安全
允許null值Key/Value均可Key不允許允許不允許

二、哈希表原理與HashMap實現

1. 哈希表核心機制

// HashMap核心存儲結構
transient Node<K,V>[] table; // 哈希桶數組static class Node<K,V> implements Map.Entry<K,V> {final int hash;    // 哈希值final K key;V value;Node<K,V> next;    // 鏈表結構
}
關鍵參數:
  • 初始容量:默認16

  • 負載因子:默認0.75(擴容閾值 = 容量 * 負載因子)

  • 樹化閾值:鏈表長度≥8時轉為紅黑樹

  • 退化閾值:紅黑樹節點≤6時退化為鏈表

2. 哈希沖突解決方案

// Java 8樹化邏輯
final void treeifyBin(Node<K,V>[] tab, int hash) {if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)resize(); // 先嘗試擴容else if ((e = tab[index = (n - 1) & hash]) != null) {TreeNode<K,V> hd = null, tl = null;do { // 轉換為TreeNode鏈表TreeNode<K,V> p = replacementTreeNode(e, null);if (tl == null)hd = p;else {p.prev = tl;tl.next = p;}tl = p;} while ((e = e.next) != null);if ((tab[index] = hd) != null)hd.treeify(tab); // 樹化操作}
}

3. 擴容機制

final Node<K,V>[] resize() {int oldCap = (oldTab == null) ? 0 : oldTab.length;int newCap = oldCap << 1; // 雙倍擴容Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];// 重新哈希分布元素for (int j = 0; j < oldCap; ++j) {Node<K,V> e;if ((e = oldTab[j]) != null) {oldTab[j] = null;if (e.next == null)newTab[e.hash & (newCap - 1)] = e;else if (e instanceof TreeNode)((TreeNode<K,V>)e).split(this, newTab, j, oldCap);else { // 鏈表優化重哈希Node<K,V> loHead = null, loTail = null;Node<K,V> hiHead = null, hiTail = null;do {if ((e.hash & oldCap) == 0) {if (loTail == null)loHead = e;elseloTail.next = e;loTail = e;}else {if (hiTail == null)hiHead = e;elsehiTail.next = e;hiTail = e;}} while ((e = e.next) != null);if (loTail != null) {loTail.next = null;newTab[j] = loHead;}if (hiTail != null) {hiTail.next = null;newTab[j + oldCap] = hiHead;}}}}return newTab;
}

三、TreeMap紅黑樹實現

1. 紅黑樹核心規則

  1. 每個節點是紅色或黑色

  2. 根節點是黑色

  3. 葉子節點(NIL)是黑色

  4. 紅色節點的子節點必須為黑色

  5. 任意節點到葉子節點的路徑包含相同數量黑色節點

2. TreeMap節點結構

static final class Entry<K,V> implements Map.Entry<K,V> {K key;V value;Entry<K,V> left;Entry<K,V> right;Entry<K,V> parent;boolean color = BLACK;
}

3. 排序實現原理

public V put(K key, V value) {Entry<K,V> t = root;if (t == null) {compare(key, key); // 檢查Comparatorroot = new Entry<>(key, value, null);size = 1;return null;}int cmp;Entry<K,V> parent;Comparator<? super K> cpr = comparator;if (cpr != null) { // 使用自定義比較器do {parent = t;cmp = cpr.compare(key, t.key);if (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;elsereturn t.setValue(value);} while (t != null);}else { // 使用自然順序if (key == null)throw new NullPointerException();Comparable<? super K> k = (Comparable<? super K>) key;do {parent = t;cmp = k.compareTo(t.key);if (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;elsereturn t.setValue(value);} while (t != null);}Entry<K,V> e = new Entry<>(key, value, parent);if (cmp < 0)parent.left = e;elseparent.right = e;fixAfterInsertion(e); // 紅黑樹平衡調整size++;return null;
}

四、HashSet與TreeSet實現

1. HashSet實現原理

// HashSet內部使用HashMap存儲
private transient HashMap<E,Object> map;// 虛擬對象用于填充Value
private static final Object PRESENT = new Object();public boolean add(E e) {return map.put(e, PRESENT)==null;
}

2. TreeSet實現原理

// TreeSet內部使用NavigableMap存儲
private transient NavigableMap<E,Object> m;public boolean add(E e) {return m.put(e, PRESENT)==null;
}

五、關鍵使用場景與最佳實踐

1. 數據結構選型指南

場景需求推薦結構原因說明
快速查找,不要求順序HashMapO(1)時間復雜度
需要有序遍歷TreeMap自然順序或自定義排序
去重集合,快速存在性檢查HashSet基于HashMap的高效實現
需要有序唯一集合TreeSet基于紅黑樹的排序特性
保持插入順序LinkedHashMap維護插入順序鏈表

2. 哈希函數最佳實踐

// 自定義對象作為Key的示例
class Employee {String id;String name;@Overridepublic int hashCode() {return Objects.hash(id, name); // 使用Java 7+的哈希工具}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Employee employee = (Employee) o;return Objects.equals(id, employee.id) &&Objects.equals(name, employee.name);}
}

3. 性能優化技巧

// HashMap初始化優化
int expectedSize = 100000;
float loadFactor = 0.75f;
int initialCapacity = (int) (expectedSize / loadFactor) + 1;
Map<String, Integer> optimizedMap = new HashMap<>(initialCapacity, loadFactor);// TreeMap自定義排序
Comparator<String> reverseComparator = Comparator.reverseOrder();
Map<String, Integer> sortedMap = new TreeMap<>(reverseComparator);

六、高級特性與注意事項

1. 并發處理方案

// 同步包裝器
Map<String, Integer> syncMap = Collections.synchronizedMap(new HashMap<>());// 并發容器
ConcurrentHashMap<String, Integer> concurrentMap = new ConcurrentHashMap<>();// 并發NavigableMap
ConcurrentSkipListMap<String, Integer> concurrentSortedMap = new ConcurrentSkipListMap<>();

2. 視圖集合操作

Map<String, Integer> map = new HashMap<>();
Set<String> keySet = map.keySet();
Collection<Integer> values = map.values();
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();// 遍歷優化
map.forEach((k, v) -> System.out.println(k + ": " + v));

3. 故障排查案例

// 內存泄漏示例
public class LeakDemo {private Map<Object, Object> map = new HashMap<>();public void add(Object key) {map.put(key, new byte[1024*1024]); // 1MB}public static void main(String[] args) {LeakDemo demo = new LeakDemo();for(int i=0; i<1000; i++) {demo.add(new Object()); // 每次new導致Key不同}}
}
// 解決方案:使用WeakHashMap或確保Key可回收

七、底層原理深度對比

1. HashMap vs TreeMap

對比維度HashMapTreeMap
數據結構數組+鏈表/紅黑樹紅黑樹
順序性無序按鍵排序
null處理允許null鍵值鍵不能為null
性能特點平均O(1)的查找O(log n)的查找
內存占用較高(數組+鏈表結構)較低(樹結構)

2. HashSet vs TreeSet

對比維度HashSetTreeSet
底層實現HashMapTreeMap
元素順序無序自然順序或Comparator定義
性能特點平均O(1)的添加/查詢O(log n)的添加/查詢
內存占用較高(存儲Entry對象)較低(樹節點結構)

八、總結與擴展方向

1. 核心要點總結

  • 選擇依據:根據順序性需求、性能要求和數據特性選擇合適結構

  • 哈希表關鍵:良好的哈希函數設計和合理的初始參數設置

  • 線程安全:并發場景使用并發容器或同步包裝器

  • 內存管理:警惕自定義對象作為Key導致的內存泄漏

2. 擴展學習方向

  • 并發容器:研究ConcurrentHashMap的分段鎖機制

  • 緩存設計:結合LinkedHashMap實現LRU緩存

  • 持久化存儲:探索TreeMap的磁盤存儲優化

  • 性能調優:使用JOL工具分析對象內存布局

通過深入理解這些核心集合類的實現原理和使用場景,開發者可以更好地根據業務需求選擇合適的數據結構,并能夠針對性地進行性能優化和問題排查。Java集合框架的設計體現了計算機科學數據結構的經典理論,值得持續深入研究和實踐。

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

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

相關文章

HTTP 1.0 和 2.0 的區別

HTTP 1.0 和 2.0 的核心區別體現在性能優化、協議設計和功能擴展上&#xff0c;以下是具體對比&#xff1a; 一、核心區別對比 特性HTTP 1.0HTTP 2.0連接方式非持久連接&#xff08;默認每次請求新建 TCP 連接&#xff09;持久連接&#xff08;默認保持連接&#xff0c;可復用…

gnome中刪除application中失效的圖標

什么是Application 這一塊的東西應該叫application&#xff0c;準確來說應該是applications。 正文 系統級&#xff1a;/usr/share/applications 用戶級&#xff1a;~/.local/share/applications ying192 ~/.l/s/applications> ls | grep xampp xampp.desktoprm ~/.local…

OpenFeign 使用教程:從入門到實踐

文章目錄 一、什么是 OpenFeign&#xff1f;1、什么是 OpenFeign&#xff1f;2、什么是 Feign&#xff1f;3、OpenFeign 與 Feign 的關系4、為什么選擇 OpenFeign&#xff1f;5、總結 二、OpenFeign 的使用步驟1. 導入依賴2. 啟用 OpenFeign3. 配置 Nacos 三、FeignClient 參數…

藍橋杯 16.對局匹配

對局匹配 原題目鏈接 題目描述 小明喜歡在一個圍棋網站上找別人在線對弈。這個網站上所有注冊用戶都有一個積分&#xff0c;代表他的圍棋水平。 小明發現&#xff0c;網站的自動對局系統在匹配對手時&#xff0c;只會將積分差恰好是 K 的兩名用戶匹配在一起。如果兩人分差小…

C#常用LINQ

在開發時發現別人的代碼使用到了LINQ十分便捷且清晰&#xff0c;這里記錄一下常用LINQ和對應的使用。參考鏈接&#xff1a;LINQ 菜鳥教程 使用的學生類和字符串用于測試 public class Student {public int StudentID;public string StudentName;public int Age; }Student[] st…

單例模式(線程安全)

1.什么是單例模式 單例模式&#xff08;Singleton Pattern&#xff09;是一種創建型設計模式&#xff0c;旨在確保一個類只有一個實例&#xff0c;并提供一個全局訪問點來訪問該實例。這種模式涉及到一個單一的類&#xff0c;該類負責創建自己的對象&#xff0c;同時確保只有單…

Python 之 __file__ 變量導致打包 exe 后路徑輸出不一致的問題

現象 做項目的時候&#xff0c;一直使用 os.path.dirname(os.path.abspath(__file__)) 來獲取當前目錄。然而&#xff0c;最近卻遇到了一個路徑相關的問題。直接運行 py 文件是正常的&#xff0c;但是打包成 exe 之后&#xff0c;卻顯示因為路徑問題導致程序報錯無法繼續執行。…

PH熱榜 | 2025-04-21

1. Google Whisk 2.0 標語&#xff1a;將圖像轉換為八秒的動畫短片。 介紹&#xff1a;Whisk 是谷歌實驗室的一項新創新&#xff0c;現在推出了 Whisk Animate——它可以將你的圖片轉換成生動的8秒視頻&#xff0c;采用了 Veo 2 技術。此功能現已在60多個國家的 Google One A…

AI大模型 —— 國產大模型 —— 華為大模型

有這么一句話&#xff0c;那就是AI大模型分兩種&#xff0c;一種是大模型&#xff1b;另一種是華為大模型。 如果從技術角度來分析&#xff0c;華為的技術不論是在軟件還是硬件都比國外的大公司差距極大&#xff0c;甚至有些技術評論者認為華為的軟硬件技術至少落后2.5代&#…

FPGA 中 XSA、BIT 和 DCP 文件的區別

在 FPGA&#xff08;現場可編程門陣列&#xff09;開發中&#xff0c;XSA、BIT 和 DCP 文件是常見的文件類型&#xff0c;它們在功能、用途、文件內容等方面存在明顯區別&#xff0c;以下是詳細介紹&#xff1a; 1. XSA 文件 定義與功能 XSA&#xff08;Xilinx Shell Archiv…

MH2103系列coremark1.0跑分數據和優化,及基于arm2d的優化應用

CoreMark 1.0 介紹 CoreMark 是由 EEMBC&#xff08;Embedded Microprocessor Benchmark Consortium&#xff09;組織于 2009 年推出的一款用于衡量嵌入式系統 CPU 或 MCU 性能的標準基準測試工具。它旨在替代陳舊的 Dhrystone 標準&#xff08;Dhrystone 容易受到各種libc不同…

云原生與AI的關系是怎么樣的?

云原生與AI的結合正在重塑現代應用的開發與部署模式&#xff0c;兩者相輔相成&#xff0c;共同推動技術創新與產業升級。以下是兩者的核心概念、結合點及未來趨勢的詳細解析&#xff1a; 一、云原生與AI的核心概念 云原生&#xff08;Cloud Native&#xff09; ? 定義&#…

【CentOs】構建云服務器部署環境

(一) 服務器采購 2 CPU4G 內存40G 系統盤 80G 數據盤 (二) 服務器安全組和端口配置 (三) 磁盤掛載 1 登錄 root 2 查看目前磁盤使用情況 df -h 3 查看磁盤掛載情況 識別哪些磁盤沒掛載 fdisk -l 4 對未掛載磁盤做分區 fdisk /dev/vdb 輸入m&#xff0…

LangChain4j語言模型選型指南:主流模型能力全景對比

LangChain4j語言模型選型指南&#xff1a;主流模型能力全景對比 前言 在大語言模型應用開發中&#xff0c;選擇合適的底層模型提供商是架構設計的關鍵決策。LangChain4j作為Java生態的重要AI框架&#xff0c;其支持的20模型提供商各有獨特的優勢場景。本文通過功能矩陣深度解…

2025.4.21日學習筆記 JavaScript String、Array、date、math方法的使用

1. String&#xff08;字符串&#xff09; String 對象用于處理和操作文本數據。 length&#xff1a;返回字符串的長度。 const str "Hello"; console.log(str.length); // 輸出: 5 charAt(index)&#xff1a;返回指定索引位置的字符。 const str "Hello…

(14)VTK C++開發示例 --- 將點投影到平面上

文章目錄 1. 概述2. CMake鏈接VTK3. main.cpp文件4. 演示效果 更多精彩內容&#x1f449;內容導航 &#x1f448;&#x1f449;VTK開發 &#x1f448; 1. 概述 計算一個點在一個平面上的投影。 vtkPlane 是 VTK&#xff08;Visualization Toolkit&#xff09;庫中的一個類&…

電子電器架構 ---軟件定義汽車的電子/電氣(E/E)架構

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 周末洗了一個澡,換了一身衣服,出了門卻不知道去哪兒,不知道去找誰,漫無目的走著,大概這就是成年人最深的孤獨吧! 舊人不知我近況,新人不知我過…

Android開發中的復制和粘貼

Android 提供了一個強大的基于剪貼板的框架&#xff0c;用于復制和粘貼。它支持簡單和復雜的數據類型&#xff0c;包括文本字符串、復雜數據結構、文本和二進制流數據&#xff0c;以及應用資源。簡單的文本數據直接存儲在剪貼板中&#xff0c;而復雜的數據則存儲為引用&#xf…

【STM32單片機】#10.5 串口數據包

主要參考學習資料&#xff1a; B站江協科技 STM32入門教程-2023版 細致講解 中文字幕 開發資料下載鏈接&#xff1a;https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwddspb 單片機套裝&#xff1a;STM32F103C8T6開發板單片機C6T6核心板 實驗板最小系統板套件科協 實驗&…

百度暑期實習崗位超3000個,AI相關崗位占比87%,近嶼智能攜AIGC課程加速人才輸出

今年3月&#xff0c;百度重磅發布3000暑期實習崗位&#xff0c;聚焦大模型、機器學習、自動駕駛等AI方向的崗位比例高達87%。此次實習崗位涉及技術研發、產品策劃、專業服務、管理支持、政企解決方案等四大類別&#xff0c;覆蓋超300個崗位細分方向。值得一提的是&#xff0c;百…