Java HashMap無死角複習

2021-09-13 03:36:34 字數 1325 閱讀 3005

每次面試都問到hashmap,回答的都不是很好,今天給它一次性的解決了

hashmap 底層是陣列和鍊錶結合在一起使用也就是鍊錶雜湊hashmap 通過 key 的 hashcode 經過擾動函式處理過後得到 hash 值,然後通過 (n - 1) & hash 判斷當前元素存放的位置(這裡的 n 指的是陣列的長度),如果當前位置存在元素的話,就判斷該元素與要存入的元素的 hash 值以及 key 是否相同,如果相同的話,直接覆蓋,不相同就通過拉鍊法解決衝突。

所謂擾動函式指的就是 hashmap 的 hash 方法。使用 hash 方法也就是擾動函式是為了防止一些實現比較差的 hashcode() 方法 換句話說使用擾動函式之後可以減少碰撞。

所謂「拉鍊法」就是:將鍊錶和陣列相結合。也就是說建立乙個鍊錶陣列,陣列中每一格就是乙個鍊錶。若遇到雜湊衝突,則將衝突的值加到鍊錶中即可。

相比於之前的版本, jdk1.8之後在解決雜湊衝突時有了較大的變化,當鍊表長度大於閾值(預設為8)時,將鍊錶轉化為紅黑樹,以減少搜尋時間。

treemap、treeset以及jdk1.8之後的hashmap底層都用到了紅黑樹。紅黑樹就是為了解決二叉查詢樹的缺陷,因為二叉查詢樹在某些情況下會退化成乙個線性結構。

為了能讓 hashmap 訪問高效,盡量較少碰撞,也就是要盡量把資料分配均勻。我們上面也講到了過了,hash 值的範圍值-2147483648到2147483647,前後加起來大概40億的對映空間,只要雜湊函式對映得比較均勻鬆散,一般應用是很難出現碰撞的。但問題是乙個40億長度的陣列,記憶體是放不下的。

所以這個雜湊值是不能直接拿來用的。用之前還要先做對陣列的長度取模運算,得到的餘數才能用來要存放的位置也就是對應的陣列下標。這個陣列下標的計算方法是「(n - 1) & hash」。(n代表陣列長度)。這也就解釋了 hashmap 的長度為什麼是2的冪次方。

這個演算法應該如何設計呢?

我們首先可能會想到採用%取餘的操作來實現。但是,重點來了:「取餘(%)操作中如果除數是2的冪次則等價於與其除數減一的與(&)操作(也就是說 hash%length==hash&(length-1)的前提是 length 是2的 n 次方;)。」並且採用二進位制位操作 &,相對於%能夠提高運算效率,這就解釋了 hashmap 的長度為什麼是2的冪次方。

concurrenthashmap 和 hashtable 的區別主要體現在實現執行緒安全的方式上不同。

360度無死角無外掛程式,教你無伺服器架構設計與公升級

無伺服器火了,為什麼受這麼多人關注?function as a service 與無伺服器有什麼區別?aws lambda azure functions 這乙個個服務的機制是什麼?如此多的疑難問題,如此新的技術領域,我們卻沒有發現一門 能 360 度解開這些問題的 serverless 課程。所以...

跳 菜,C 全方位無死角防禦,亞歷山卓中

damn it 我tm 好菜!策略框架大局 1.c c 基礎 stl boost 11 14 cpp c 11 14 stl boost 5.其他 ros 注意注意注意 不要鋪的太開了,沒必要什麼都懂,專業點我的哥。ros有餘力再去看,核心在前3個。調整 按目前狀態和時間,演算法和資料結構就夠嗆了。...

消毒機械人歡樂消 自主巡航消毒,360 無死角消毒

近日,在全國有序復工復業 線下市場回暖的背景下,沉寂已久的線下消費場所開始營業。但肺炎疫情還沒完程式設計客棧全結束,門店除了對員工進行日常的體溫檢測 要求其佩戴口罩手套之外,對室內進行定期消毒清潔也是極為關鍵的安防措施。國內智慧型配送機械人標桿企業普渡科技經過深入調研,針對人員密度高 流動性強的室內...