1、請你談談 HashMap 的工作原理
如果被問到 HashMap 相關的問題,它的工作原理都會被作為面試的開場白,這個時候先裝作若有所思的樣子冷靜一下。首先 HashMap 是基於 hashing 的原理,我們知道 HashMap 有兩個常用的方法 put()、get(),將鍵值對傳遞給 put() 方法時,它調用鍵對象的 hashCode() 方法來計算 hashcode,然后找到 bucket 位置來儲存值對象。當獲取對象時,通過鍵對象的equals() 方法找到正確的鍵值對,然后返回值對象。
一般情況下,肯定會問如果不同的鍵對象的 hashcode 值相等會出現什么樣的情況。他們肯定是存儲在同一個位置的鏈表中的,使用鍵對象的 equals() 方法找到鍵值對。
HashMap + 鏈表 + 紅黑樹 的圖片引用自 開源中國
在 Java1.8 以后,HashMap 在數組、鏈表的基礎上又增加了紅黑樹的數據結構。在一個數組位置的鏈表長度大於 8 時數據結構轉換為紅黑樹的結構。
2、HashMap 和 HashTable 的區別有什么?
HashMap 和 HashTable 都實現了 Map 接口,主要的區別集中在線程、同步、速度方面的差別。
HashMap 是非同步的,並且 HashMap 可以存儲鍵值為 null 的對象,允許最多只有一個鍵可以為 null 對象、允許可以有多個值為 null。
HashMap 是線程不安全的,HashTable 是線程安全的。
因為 HashTable 是多線程的,所以在單線程的情況下,HashMap 的速度要快一些。
HashMap 不能保證存儲順序是不變的。
3、HashMap 和 HashSet 的區別有什么?
兩者實現的接口不一樣,HashMap 實現的是 Map 接口、HashSet 則實現的是 Set 接口。
HashMap 存儲的是鍵值對、HashSet 存儲的是對象。
HashSet 的速度比 HashMap 的要慢一些。
計算 hashcode 值的方式不一樣,HashMap 使用鍵對象來計算、HashSet 使用它本身的對象元素來計算。
4、當兩個對象的 HashCode 相同會發生什么?
因為hashcode相同,所以它們的bucket位置相同,‘碰撞’會發生。因為HashMap使用鏈表存儲對象,這個Entry(包含有鍵值對的Map.Entry對象)會存儲在鏈表中。
5、如果兩個鍵的 HashCode 相同,你如何獲取值對象?
當我們調用get()方法,HashMap會使用鍵對象的hashcode找到bucket位置,然后獲取值對象。找到bucket位置之后,會調用keys.equals()方法去找到鏈表中正確的節點,最終找到要找的值對象。
6、多線程情況下,調整 HashMap 的大小會有什么問題?
由於線程不安全的原因,在多線程條件下調整 HashMap 的大小時會存在多個 HashMap 對象的競爭關系,不知道要給哪一個調整大小。如此一來,多線程情況調整 HashMap 的大小就會陷入死循環的情況,在 Java1.5 以后就增加了 ConcurrentHashMap 的對象解決多線程等問題。
更多精彩前往微信公眾號【老王說編程】,專注后端編程實戰,原創文章每天更新!