HasMap 底層原始碼分析
目錄
一、什麼是雜湊表
二、HashMap實現原理
三、為何HashMap的陣列長度一定是2的次冪?
四、重寫equals方法需同時重寫hashCode方法
一、什麼是雜湊表
在討論雜湊表之前,我們先大概瞭解下其他資料結構在新增,查詢等基礎操作執行效能
陣列:採用一段連續的儲存單元來儲存資料。對於指定下標的查詢,時間複雜度為O(1);通過給定值進行查詢,需要遍歷陣列,逐一比對給定關鍵字和陣列元素,時間複雜度為O(n),當然,對於有序陣列,則可採用二分查詢,插值查詢,斐波那契查詢等方式,可將查詢複雜度提高為O(logn);對於一般的插入刪除操作,涉及到陣列元素的移動,其平均複雜度也為O(n)
線性連結串列:對於連結串列的新增,刪除等操作(在找到指定操作位置後),僅需處理結點間的引用即可,時間複雜度為O(1),而查詢操作需要遍歷連結串列逐一進行比對,複雜度為O(n)
二叉樹:對一棵相對平衡的有序二叉樹,對其進行插入,查詢,刪除等操作,平均複雜度均為O(logn)。
雜湊表:相比上述幾種資料結構,在雜湊表中進行新增,刪除,查詢等操作,效能十分之高,不考慮雜湊衝突的情況下,僅需一次定位即可完成,時間複雜度為O(1),接下來我們就來看看雜湊表是如何實現達到驚豔的常數階O(1)的。
我們知道,資料結構的物理儲存結構只有兩種:順序儲存結構和鏈式儲存結構(像棧,佇列,樹,圖等是從邏輯結構去抽象的,對映到記憶體中,也這兩種物理組織形式),而在上面我們提到過,在陣列中根據下標查詢某個元素,一次定位就可以達到,雜湊表利用了這種特性,雜湊表的主幹就是陣列。
比如我們要新增或查詢某個元素,我們通過把當前元素的關鍵字 通過某個函式對映到陣列中的某個位置,通過陣列下標一次定位就可完成操作。
儲存位置 = f(關鍵字)
其中,這個函式f一般稱為雜湊函式,這個函式的設計好壞會直接影響到雜湊表的優劣。舉個例子,比如我們要在雜湊表中執行插入操作:
查詢操作同理,先通過雜湊函式計算出實際儲存地址,然後從陣列中對應地址取出即可。
雜湊衝突
然而萬事無完美,如果兩個不同的元素,通過雜湊函式得出的實際儲存地址相同怎麼辦?也就是說,當我們對某個元素進行雜湊運算,得到一個儲存地址,然後要進行插入的時候,發現已經被其他元素佔用了,其實這就是所謂的雜湊衝突,也叫雜湊碰撞。前面我們提到過,雜湊函式的設計至關重要,好的雜湊函式會盡可能地保證 計算簡單和雜湊地址分佈均勻,但是,我們需要清楚的是,陣列是一塊連續的固定長度的記憶體空間,再好的雜湊函式也不能保證得到的儲存地址絕對不發生衝突。那麼雜湊衝突如何解決呢?雜湊衝突的解決方案有多種:開放定址法(發生衝突,繼續尋找下一塊未被佔用的儲存地址),再雜湊函式法,鏈地址法,而HashMap即是採用了鏈地址法,也就是陣列+連結串列的方式,
二、HashMap實現原理
HashMap的主幹是一個Entry陣列。Entry是HashMap的基本組成單元,每一個Entry包含一個key-value鍵值對。
//HashMap的主幹陣列,可以看到就是一個Entry陣列,初始值為空陣列{},主幹陣列的長度一定是2的次冪,至於為什麼這麼做,後面會有詳細分析。
transient Entry
相關文章
- Owin Katana 的底層原始碼分析原始碼
- JAVA ArrayList集合底層原始碼分析Java原始碼
- ArrayList底層結構和原始碼分析原始碼
- Android Compose 入門,深入底層原始碼分析Android原始碼
- Seata原始碼分析(一). AT模式底層實現原始碼模式
- 持久層Mybatis3底層原始碼分析,原理解析MyBatisS3原始碼
- iOS底層原理總結 -- 利用Runtime原始碼 分析Category的底層實現iOS原始碼Go
- ThreadLocal底層原始碼解析thread原始碼
- Redis原始碼分析-底層資料結構盤點Redis原始碼資料結構
- Laravel 執行原理分析與原始碼分析,底層看這篇足矣Laravel原始碼
- 位元組碼底層分析String
- 探究synchronized底層原理(基於JAVA8原始碼分析)synchronizedJava原始碼
- PHP 底層原始碼下載地址PHP原始碼
- 深入分析Java中的PriorityQueue底層實現與原始碼Java原始碼
- SpringBoot原始碼分析之條件註解的底層實現Spring Boot原始碼
- 筆記-runtime原始碼解析之讓你徹底瞭解底層原始碼筆記原始碼
- spring原始碼解析 (七) 事務底層原始碼實現Spring原始碼
- PHP底層核心原始碼之變數PHP原始碼變數
- ArrayList 從原始碼角度剖析底層原理原始碼
- Golang 切片(Slice)底層原始碼閱讀Golang原始碼
- RocketMQ基礎概念剖析,並分析一下Producer的底層原始碼MQ原始碼
- Golang WaitGroup 底層原理及原始碼詳解GolangAI原始碼
- HashMap底層資料結構原始碼解析HashMap資料結構原始碼
- 原始碼防洩密的底層安全基石原始碼
- RabbitMq底層原理分析MQ
- 圖解Janusgraph系列-圖資料底層序列化原始碼分析(Data Serialize)圖解原始碼
- 屬性填充底層原始碼深入剖析前戲原始碼
- React Native 0.55.4 Android 原始碼分析(Java層原始碼解析)React NativeAndroid原始碼Java
- HashMap的底層原理分析HashMap
- Java集合類,從原始碼解析底層實現原理Java原始碼
- Java併發集合類ConcurrentHashMap底層核心原始碼解析JavaHashMap原始碼
- 透過表層“效果”,築牢原始碼防洩密底層安全基石原始碼
- MyBatis原始碼分析之核心處理層MyBatis原始碼
- Flutter之Android層面原始碼分析(一)FlutterAndroid原始碼
- 【Flink】Flink 底層RPC框架分析RPC框架
- Mybatis底層原理學習(二):從原始碼角度分析一次查詢操作過程MyBatis原始碼
- 精盡 MyBatis 原始碼分析 - 基礎支援層MyBatis原始碼
- HashMap原始碼分析(二):看完徹底瞭解HashMapHashMap原始碼