hashmap底層實現原理,職場必問,解決hash衝突

**```
hashmap數組和鏈表的結合體
1、HashMap 是不是有序的?不是有序的。
2、有沒有有序的Map實現類呢?有 TreeMap 和 LinkedHashMap。
3、然後問TreeMap 和 LinkedHashMap 是如何保證它的順序的? TreeMap 是通過實現 SortMap 接口,能夠把它保存的鍵值對根據 key 排序,基於紅黑樹,從而保證 TreeMap 中所有鍵值對處於有序狀態。LinkedHashMap 則是通過插入排序(就是你 put 的時候的順序是什麼,取出來的時候就是什麼樣子)和訪問排序(改變排序把訪問過的放到底部)讓鍵值有序。
4、你覺得它們兩個(Treemap和LinkedHashMap)哪個的有序實現比較好?如果你依然可以回答的話,那麼繼續問你,你覺得還有沒有比它更好或者更高效的實現方式?
爲什麼要使用HashMap?
HashMap是一個散列桶(數組和鏈表),它存儲的內容是鍵值對key-value映射
HashMap採用了數組和鏈表的數據結構,能在查詢和修改方面繼承了數組的線性查詢和鏈表的尋址修改
HashMap是非synchronized的,線程不安全,所以很快
HashMap可以接受null鍵和值,而HashTable不行(因爲equals()方法需要對象,因爲HashMap是後出的api經過處理纔可以)
HashMap的工作原理是什麼?
然後講下HashMap中的實現原理,hashmap是由數組和鏈表組成的。數組是HashMap的本體,而鏈表則是爲了解決hash衝突而存在的,如果定位到數組位置不存在鏈表(當前Entry的next指向爲null),那麼對於查找插入等操作很快,僅僅需要一次尋址即可;如果定位到數組有鏈表,對於添加操作其時間複雜度爲O(n),首先遍歷鏈表,存在既覆蓋,否則新增。對於查找操作來講,仍需遍歷鏈表,然後通過key對象的equals方法逐一比對查找。所以,性能考慮,HashMap中的鏈表出現越少,性能纔會越好。
添加元素操作步驟:
以下是具體的 put 過程(JDK1.8)
對 Key 求 Hash 值,然後再計算下標
如果沒有碰撞,直接放入桶中(碰撞的意思是計算得到的 Hash 值相同,需要放到同一個 bucket 中)如果碰撞了,以鏈表的方式鏈接到後面
如果鏈表長度超過閥值(TREEIFY THRESHOLD==8),就把鏈表轉成紅黑樹,鏈表長度低於6,就把紅黑樹轉回鏈表
如果節點已經存在就替換舊值
如果桶滿了(容量16*加載因子0.75),就需要 resize(擴容2倍後重排)
減少hash衝突?擾動函數可以減少碰撞

  • 原理是如果兩個不相等的對象返回不同的 hashcode 的話,那麼碰撞的機率就會小些。這就意味着存鏈表結構減小,這樣取值的話就不會頻繁調用
    equal 方法,從而提高 HashMap 的性能(擾動即 Hash 方法內部的算法實現,目的是讓不同對象返回不同hashcode)。

  • 使用不可變的、聲明作 final 對象,並且採用合適的 equals() 和 hashCode()
    方法,將會減少碰撞的發生不可變性使得能夠緩存不同鍵的 hashcode,這將提高整個獲取對象的速度,使用 String、Integer
    這樣的 wrapper 類作爲鍵是非常好的選擇。 爲什麼 String、Integer 這樣的 wrapper 類適合作爲鍵?
    因爲 String 是 final,而且已經重寫了 equals() 和 hashCode() 方法了。不可變性是必要的,因爲爲了要計算 hashCode(),就要防止鍵值改變,如果鍵值在放入時和獲取時返回不同的 hashcode 的話,那麼就不能從 HashMap 中找到你想要的對象。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章