陣列和鏈表都是存盤一個物件,HashMap 存盤資料是以 一對資料來存盤,即鍵值對【key(物件)---->value(物件)】,
JDK1.8版本之前,HashMap的實作: 陣列 + 鏈表;
JDK1.8版本之后,HashMap的實作: 陣列 + 鏈表 / 二叉樹(紅黒樹);
陣列的默認大小是16,加載因子【DEFAULT_LOAD_FACTOR】默認值是0.75f,表示當陣列容量達到75%,陣列會被重新擴充,陣列的最大容量是整數最大值的一半,
HashMap存盤資料結構中鏈表與二叉樹的轉化條件: 是鍵值對的總數大于64,且
a.在擴容時,當哈希表中陣列同一個位置的鏈表長度大于8時(閥值),那么會把鏈表轉換成紅黑樹,來提高查詢效率;
b.在擴容時,當哈希表中陣列同一個位置的鏈表長度小于6時(閥值),那么會把紅黑樹轉換成鏈表,來提高查詢效率,
閥值為什么是8 和 6? (防抖)減少鏈表與二叉樹之間的轉換頻率,避免影響性能,
哈希表:這個是因為存盤資料的方式被稱為哈希(演算法),Object類中hashCode方法是一個本地方法:表示此方法的具體實作是由 C、C++來實作的,哈希值(),
同一個物件,我們要保證在運行期hashCode值是相同的,如果不同那么此物件在哈希表中會有記憶體泄露問題,
記憶體泄露:由于物件在運行程序中,hashCode不同,導致該物件在哈希表中無法找到,
哈希表存盤資料的演算法:通過計算key物件的hashCode值,來確認key物件在哈希表陣列中的存盤位置,目的是為了可以通過計算hash值快速的查找物件,同一個物件,hashCode值相同,不同的物件,hashCode可能相同,因為整數是有限的,
使用hashCode計算物件的hash值:return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16),
怎么擴容?初始化大小?
a.在第一次put資料的時候初始化;
b.在put方法中實作,擴容演算法是 oldCap << 1 表示乘于2;
c.每次擴容哈希表,會導致所有已存盤的物件重新計算哈希值,存盤到新的哈希表中(重新散列),所以在hashMap中,物件所在的位置不保證永遠不變(無序),重新散列會導致重新計算所有物件,消耗性能,在可預知的情況下,散列次數越少越好,
HashMap的優點與缺點?
優點:取值快,資料量越大越明顯;
缺點:執行緒不安全,避免頻繁散列(rehash),合理的使用new HashMap<>(initialCapacity);初始容量,來減少散列,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/92569.html
標籤:Java
