前言
HashMa是Java中最常用的集合類框架,也是Java語言中非常典型的數據結構,同時也是我們需要掌握的數據結構,更重要的是進大廠面試必問之一。
數組特點
存儲區間是連續,且佔用內存嚴重,空間複雜也很大,時間複雜為O(1)。優點:是隨機讀取效率很高,原因數組是連續(隨機訪問性強,查找速度快)。缺點:插入和刪除數據效率低,因插入數據,這個位置後面的數據在內存中要往後移的,且大小固定不易動態擴展。鍊表特點
區間離散,佔用內存寬鬆,空間複雜度小,時間複雜度O(N)。優點:插入刪除速度快,內存利用率高,沒有大小固定,擴展靈活。缺點:不能隨機查找,每次都是從第一個開始遍歷(查詢效率低)。哈希表特點
以上數組和鍊表,大家都知道各自優缺點。那麼我們能不能把以上兩種結合一起使用,從而實現查詢效率高和插入刪除效率也高的數據結構呢?答案是可以滴,那就是哈希表可以滿足,接下來我們一起複習HashMap中的put()和get()方法實現原理。
HashMap的put()和get()的實現
1、map.put(k,v)實現原理
第一步首先將k,v封裝到Node對象當中(節點)。第二步它的底層會調用K的hashCode()方法得出hash值。第三步通過哈希表函數/哈希算法,將hash值轉換成數組的下標,下標位置上如果沒有任何元素,就把Node添加到這個位置上。如果說下標對應的位置上有鍊表。此時,就會拿著k和鍊表上每個節點的k進行equal。如果所有的equals方法返回都是false,那麼這個新的節點將被添加到鍊表的末尾。如其中有一個equals返回了true,那麼這個節點的value將會被覆蓋。
2、map.get(k)實現原理
第一步:先調用k的hashCode()方法得出哈希值,並通過哈希算法轉換成數組的下標。第二步:通過上一步哈希算法轉換成數組的下標之後,在通過數組下標快速定位到某個位置上。重點理解如果這個位置上什麼都沒有,則返回null。如果這個位置上有單向鍊表,那麼它就會拿著參數K和單向鍊表上的每一個節點的K進行equals,如果所有equals方法都返回false,則get方法返回null。如果其中一個節點的K和參數K進行equals返回true,那麼此時該節點的value就是我們要找的value了,get方法最終返回這個要找的value。
3、為何隨機增刪、查詢效率都很高的原因是?
原因:增刪是在鍊表上完成的,而查詢只需掃描部分,則效率高。
HashMap集合的key,會先後調用兩個方法,hashCode and equals方法,這這兩個方法都需要重寫。
4、為什麼放在hashMap集合key部分的元素需要重寫equals方法?
因為equals默認比較是兩個對象內存地址
HashMap集合的key特點:
5、HashMap總結
無序,不可重複為什麼是無序的?因為不一定掛到哪一個單向鍊表上的,因此加入順序和取出也不一樣。怎麼保持不可重複?使用equals方法來保證HashMap集合key不可重複,如key重複來,value就會覆蓋。存放在HashMap集合key部分的元素,其實就是存放在HashSet集合中,則HashSet集合也需要重寫equals和hashCode方法。hashmap集合的默認初始化容量為16,默認加載因子為0.75,也就是說這個默認加載因子是當hashMap集合底層數組的容量達到75%時,數組就開始擴容。hashmap集合初始化容量是2的陪數,為了達到散列均勻,提高hashmap集合的存取效率,
6、注意JDK8之後
JDK8之後,如果哈希表單向鍊表中元素超過8個,那麼單向鍊表這種數據結構會變成紅黑樹數據結構。當紅黑樹上的節點數量小於6個,會重新把紅黑樹變成單向鍊表數據結構。
問題:
如果O1和O2的hash值相同,就會存放到同一個單向鍊表上,
如果不同,但由於哈希算法執行結束之後轉換的數組下標可能相同,此時會發上「哈希碰撞」。
7、高頻面試題
HashMap的工作原理是什麼?HashMap中的「死鎖」是怎麼回事?HashMap中能put兩個相同key嗎?為什麼?HashMap中的鍵值可以為null嗎?原理?HashMap擴容機制?很感謝各位人才能看到這裡,如果需要大數據、Java教程可以關注我,私信發送「Java、Springboot、mysql」等相關術語,即可獲取更多教程。
熬夜不易,創作不易,各位的支持和認可,就是我創作的最大動力,我們下篇文章見!如排版或者哪裡寫得不夠好,歡迎評論區一起交流。