java面試散列表及樹所對應(yīng)容器類及HashMap沖突解決全面分析
散列表 Hashmap、hashtable、concurrentHashMap、hashset
;
樹: treemap、treeset、hashset
treeset 繼承自 treemap,hashset 繼承自 hashmap ;
性能分析
Map 是 Java 中的接口,Map.Entry 是 Map 的一個內(nèi)部接口 Map 提供了一些常用方法,例如 keySet()、entrySet() 方法等;
Entry: key 和 value的組合,即為一個映射項<K,V>
Treemap 底層數(shù)據(jù)結(jié)構(gòu)是紅黑樹,元素存儲是有序的,因此添加元素需要循環(huán)查找 Entry 插入位置、取出元素時需要遍歷才能找到合適的 Entry ,比較耗性能;treemap、treeset 對比 hashmap、hashset 優(yōu)勢:前者元素都以有序狀態(tài)排列
HashMap 產(chǎn)生沖突原因及解決方法
調(diào)用hashCode() 計算 hashCode ,兩個不同對象可能有相同的 hashCode ,導(dǎo)致沖突產(chǎn)生,
bucket ,哈希表中的數(shù)組中可以存儲 hashcode 相同對象,每個bucket 都有其指定索引,系統(tǒng)可以根據(jù)索引快速訪問該 bucket 里存儲的元素
HashMap 解決沖突方法
1,開放定址法:通過探測算法,檔一個槽位被占用情況下繼續(xù)查找下一個;
探測算法的三種方式:
- 線性探查
- 二次探查
- 雙重散列 采用兩個輔助散列函數(shù)合成一個:
h1
、h2
為兩個散列函數(shù)
2,鏈地址法:數(shù)組+鏈表,將hash 值相同對象組織為一個鏈表放在 hash值對應(yīng)的 bucket
3,再哈希,準(zhǔn)備多個散列函數(shù),當(dāng)發(fā)生沖突時再選擇一個散列函數(shù)進(jìn)行散列,原理與雙重散列相似
jdk7 與 jdk8 中HashMap的區(qū)別
發(fā)生沖突
- jdk7 中 hashMap 采用數(shù)組+鏈表。如果過多節(jié)點在 hash 時發(fā)生碰撞,如果要查找其中一個節(jié)點,需要
O(n)
的查找時間。 - jdk8 中 hashMap 采用數(shù)組+鏈表/紅黑樹,出現(xiàn) hash 沖突時會進(jìn)行判斷,該節(jié)點是紅黑樹還是量表:
如果是鏈表的話,數(shù)據(jù)插入鏈表尾部并判斷鏈表長度是否達(dá)到某個閾值(默認(rèn)閾值為 8 ),如果大于閾值,鏈表將轉(zhuǎn)化為紅黑樹,時間復(fù)雜度為O(nlogn);
若是紅黑樹的話, 直接插入紅黑樹即可;
數(shù)據(jù)結(jié)構(gòu)紅黑樹的幾個性質(zhì),查詢效率非常高,10億數(shù)據(jù)進(jìn)行不到30次比較就能查找到目標(biāo)
1、每個節(jié)點要么是黑色、要么是紅色;
2、根節(jié)點是黑色;
3、每個葉子節(jié)點是黑色;
4、每個紅色節(jié)點的兩個子結(jié)點一定都是黑色;
5、任意一結(jié)點到每個葉子節(jié)點的路徑都包含相同數(shù)量的黑節(jié)點;
擴(kuò)容
JDK7 擴(kuò)容時,在 resize() 過程中采用頭插法,舊數(shù)據(jù)轉(zhuǎn)移到新數(shù)組中,轉(zhuǎn)移操作=正序遍歷倆表,在頭部依次插入,即鏈表逆序;多線程下 resize() 容易出現(xiàn) 死循環(huán),在多線程下并發(fā)執(zhí)行 put() 操作,一旦出現(xiàn)擴(kuò)容情況,容易出現(xiàn)環(huán)形鏈表,在獲取數(shù)據(jù)、遍歷鏈表時出現(xiàn)死循環(huán),即死鎖轉(zhuǎn)發(fā)太;
JDK 8 在擴(kuò)容 resize() 時,數(shù)據(jù)轉(zhuǎn)移時在新鏈表尾部依次插入,不會出現(xiàn)逆序、環(huán)形鏈表情況,但 jdk 1.8 仍是線程不安全的
使用建議
1,使用出初始值,避免多次擴(kuò)容的性能消耗;
2,自定義對象作為 key,時需要重寫 hashCode 、equals 方法;
3,多線程下, 使用 CurrentHashMap 代替 HashMap;
Reference
1, http://chabaoo.cn/article/224721.htm
2, https://www.jianshu.com/p/e136ec79235c
3, https://zhuanlan.zhihu.com/p/59250175
以上就是java面試之散列表及樹所對應(yīng)容器類及HashMap沖突解決的詳細(xì)內(nèi)容,更多關(guān)于java散列表樹所對應(yīng)容器類HashMap沖突的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java旋轉(zhuǎn)數(shù)組中最小數(shù)字具體實現(xiàn)(圖文詳解版)
這篇文章主要給大家介紹了關(guān)于Java旋轉(zhuǎn)數(shù)組中最小數(shù)字具體實現(xiàn)的相關(guān)資料,旋轉(zhuǎn)數(shù)組,說明數(shù)據(jù)不變,只是改變位置,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2023-08-08java:程序包javafx.geometry不存在問題及解決
這篇文章主要介紹了java:程序包javafx.geometry不存在問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08Java中調(diào)用Python的實現(xiàn)示例
本文主要介紹了Java中調(diào)用Python的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05spring自定義注解實現(xiàn)攔截器的實現(xiàn)方法
本篇文章主要介紹了spring自定義注解實現(xiàn)攔截器的實現(xiàn)方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-08-08關(guān)于各種排列組合java算法實現(xiàn)方法
這篇文章介紹了幾種用JAVA實現(xiàn)的排列組合算法,有需要的朋友可以參考一下2013-06-06Java反射 JavaBean對象自動生成插入,更新,刪除,查詢sql語句操作
這篇文章主要介紹了Java反射 JavaBean對象自動生成插入,更新,刪除,查詢sql語句操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08