HashMap面试常问问题
最近在準備秋招面試,集合知識的儲備在面試過程中必不可少,雖然現在已經到了jdk11,但是好多公司暫時還是jdk.1.8,并且jdk.1.8的新特性,在HashMap這里是一個大突破
-
jdk1.8中紅黑樹的加入
-
jdk1.7變為鏈表的頭插法以及jdk1.8的尾插法區別
-
concurrentHashMap的出現
所以由HashMap進入,可以問關于線程高并發的安全問題引入到并發鎖的對比,或者可以由數組,鏈表到達紅黑樹引入數據結構的問題。可見HashMap的基礎 直接決定了會不會有下面問題的擴展,掌握這個勢在必得。
很多人懂這個的原理,但是心中的理解表達不出來,這樣子在面試中真的很虧。
下面總結了常見的HashMap的面試問題,下面直接附加有答案,感覺自己沒有把握的可以直接背過。
一、什么是HashMap?
HashMap是一個用于存儲Key-Value鍵值對的集合,每一個鍵值對也叫做Entry。這些個鍵值對(Entry)分散存儲在一個數組當中,這個數組就是HashMap的主干,數組每一個元素的初始值都是Null。這些就是HashMap的定義了。
點到為止,有的面試官不喜歡說的過多。如果想要輸的多一點,,可以參考文末的總結
二、你為什么用到它?
HashMap可以接受null鍵值和值,而Hashtable則不能;
HashMap是非synchronized,所以相對而說,HashMap很快;
以及HashMap儲存的是鍵值對,以一種數據之間的對應關系。
三、你知道HashMap的工作原理嗎?
這時候慢慢的進入集合的問題狀態了,準備好面對10分鐘左右吧
HashMap是基于hashing的原理,我們使用put(key,
value)存儲對象到HashMap中,使用get(key)從HashMap中獲取對象。
當我們給put()方法傳遞鍵和值時,我們先對鍵調用hashCode()方法,返回的hashCode用于找到bucket位置來儲存Entry對象。”這里關鍵點在于指出,HashMap是在bucket中儲存鍵對象和值對象,作為Map.Entry。
四、你知道HashMap的get()方法的工作原理嗎?
首先根據對象的Hash值進行數組方面的尋找,然后找到這個數組之后,判斷key是不是唯一,如果key唯一,則直接返回,如果不唯一,則使用equals進行值的判斷,最后返回數據。
五、當兩個對象的hashcode相同會發生什么?
【這個問題基本上就是分界點了】
一些面試者會回答因為hashcode相同,所以兩個對象是相等的,HashMap將會拋出異常,或者不會存儲它們。
如果之前的問題回答的好,面試官的印象比較好,可能會提醒他們有equals()和hashCode()兩個方法,并告訴他們兩個對象就算hashcode相同,但是它們可能并不相等。
如果掌握的不太好,一些面試者可能就此放棄。那下面的問題也就不了了之了,等于放棄了一個很好的機會。
而這個問題的答案是:因為hashcode相同,所以它們的bucket位置相同,‘碰撞’會發生。因為HashMap使用鏈表存儲對象,這個Entry(包含有鍵值對的Map.Entry對象)會存儲在鏈表中。這個時候要理解根據hashcode來劃分的數組,
如果數組的坐標相同,則進入鏈表這個數據結構中了,jdk1.7及以前為頭插法,jdk1.8之后是尾插法,在jdk1.8之后,當鏈表長度到達8的時候,jdk1.8上升為紅黑樹,
這樣說,無疑是直接的加分項。有的面試官直接跳入數據結構,有的會直接繼續挖掘。
六、如果兩個鍵的hashcode相同,你如何獲取值對象?
當我們調用get()方法,HashMap會使用鍵對象的hashcode找到bucket位置,然后獲取值對象,如果有兩個值對象儲存在同一個bucket,將會遍歷鏈表直到找到值對象。找到bucket位置之后,會調用keys.equals()方法去找到鏈表中正確的節點,最終找到要找的值對象。
【完美的答案!】
請注意:
許多情況下,面試者會在這個環節中出錯,因為他們混淆了hashCode()和equals()方法。
因為在此之前hashCode()屢屢出現,而equals()方法僅僅在獲取值對象的時候才出現。
一些優秀的開發者會指出使用不可變的、聲明作final的對象,并且采用合適的equals()和hashCode()方法的話,將會減少碰撞的發生,提高效率。
不可變性使得能夠緩存不同鍵的hashcode,這將提高整個獲取對象的速度,使用String,Interger這樣的wrapper類作為鍵是非常好的選擇。
七、如果HashMap的大小超過了負載因子(load factor)定義的容量,怎么辦?
【問到這個問題之后,要及時的意識到面試官要把你往線程安全的方向引入了,做好準備。】
默認的負載因子大小為0.75,也就是說,當一個map填滿了75%的bucket時候,和其它集合類(如ArrayList等)一樣,將會創建原來HashMap大小的兩倍的bucket數組,來重新調整map的大小,并將原來的對象放入新的bucket數組中。這個過程叫作rehashing,因為它調用hash方法找到新的bucket位置。
八、你了解重新調整HashMap大小存在什么問題嗎?
你可能回答不上來,這時面試官會提醒你當多線程的情況下,可能產生條件競爭(race condition)。
當重新調整HashMap大小的時候,確實存在條件競爭,因為如果兩個線程都發現HashMap需要重新調整大小了,它們會同時試著調整大小。在調整大小的過程中,存儲在鏈表中的元素的次序會反過來,因為移動到新的bucket位置的時候,HashMap并不會將元素放在鏈表的尾部,而是放在頭部,這是為了避免尾部遍歷(tail traversing),原數組[j]位置上的桶移到了新數組[j+原數組長度]。如果條件競爭發生了,那么就死循環了。
(如果線程方面的知識儲備還不錯,那這個時候,你可以質問面試官,為什么這么奇怪,要在多線程的環境下使用HashMap呢?,不直接使用concurrentHashMap)
然后,恭喜你,你的線程面試開始啦!!!
如果讀者對這個問題感興趣,可以再來看看這些問題設計哪些知識點:
● hashing的概念
● HashMap中解決碰撞的方法
● equals()和hashCode()的應用,以及它們在HashMap中的重要性
● 不可變對象的好處
● HashMap多線程的條件競爭
● 重新調整HashMap的大小
總結
HashMap的工作原理
HashMap基于hashing原理,我們通過put()和get()方法儲存和獲取對象。當我們將鍵值對傳遞給put()方法時,它調用鍵對象的hashCode()方法來計算hashcode,讓后找到bucket位置來儲存值對象。當獲取對象時,通過鍵對象的equals()方法找到正確的鍵值對,然后返回值對象。HashMap使用鏈表來解決碰撞問題,當發生碰撞了,對象將會儲存在鏈表的下一個節點中。 HashMap在每個鏈表節點中儲存鍵值對對象。
當兩個不同的鍵對象的hashcode相同時會發生什么? 它們會儲存在同一個bucket位置的鏈表中。鍵對象的equals()方法用來找到鍵值對。
總結
以上是生活随笔為你收集整理的HashMap面试常问问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 通达信板块监控指标_通达信板块监测指标公
- 下一篇: pytorch读取常用数据集datase