更新時間:2023-02-03 14:12:13 來源:動力節點 瀏覽1674次
現在網上有關hashmap面試題的資料可以說是五花八門的,有的只有問題沒有回答,有的有回答沒有解答思路,這就讓我們很難參考了。在我們的面試中除了要征服面試官,讓面試官看到我們的技術功底,也是面試者之間的pk,面試的人再多,企業也只招收那么幾名,所以,我們要展現出最好的優勢。從面試題下手,可以很大程度上增加我們的就業機會。
1.HashMap的擴容方式?負載因子是多少?為什是這么多?
加載因子設置為0.75而不是1,是因為設置過大,桶中鍵值對碰撞的幾率就會越大,同一個桶位置可能會存放好幾個value值,這樣就會增加搜索的時間,性能下降,設置過小也不合適,如果是0.1,那么10個桶,threshold為1,你放兩個鍵值對就要擴容,太浪費空間了。
2.HashMap的主要參數都有哪些?
//默認的map大小,為2的n次冪
static final int DEFAULT_INITIAL_CAPACITY(默認初始容量) = 1 << 4; // aka 16
// 最大容量,指定的值超過 2的30次冪,默認使用這個值
static final int MAXIMUM_CAPACITY (最大容量)= 1 << 30;
//在構造函數中沒有指定時使用的負載因子
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//當鏈表長度為8時,使用以紅黑樹代替鏈表,紅黑樹的結點是鏈表長度的兩倍,當比較短的時候,使用紅黑樹的效率其實并不高,根據泊松分布公式的統計結果,在結點數達到8時,適合使用紅黑樹
static final int TREEIFY_THRESHOLD(恐嚇的閾值) = 8;
// 紅黑樹轉為鏈表的閾值
static final int UNTREEIFY_THRESHOLD (非恐嚇的閾值)= 6;
//鏈表轉紅黑樹時數組的大小的閾值,即數組大小大于這個數字時且鏈表長度大于8才會轉為紅黑樹,
//在數組長度小于64,不會轉,而是進行擴容
static final int MIN_TREEIFY_CAPACITY = 64(小的恐嚇容量);
3.HashMap是怎么處理hash碰撞的?
如果key相同,則會替換key對應的內容最最小值,key不相同,則接到后面的鏈表,如果鏈表長度到達8且數組的長度大于64時,則將鏈表轉為紅黑樹,如果數組長度小于64,則是進行擴容
4.hash的計算規則?
將對象的hashcode()方法返回的hash值,進行無符號的右移16位,并與原來的hash值進行按位異或操作,目的是將hash的低16bit和高16bit做了一個異或,使返回的值足夠散列
在get和put的過程中,計算下標時,先對hashCode進行hash操作,然后再通過hash值進一步計算下標。
5.如何解決初始化,輸入的值不是2的n次冪
/**
* Returns a power of two size for the given target capacity.
*/
static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
6.HashMap的數據插入原理是怎樣的
面試者:如果你能按以下思路回答,堪稱完美!
先判斷數組是否為空,為空進行初始化;
不為空,計算 k 的 hash 值,通過(n - 1) & hash計算應當存放在數組中的下標 index;
查看 table[index] 是否存在數據,沒有數據就構造一個Node節點存放在 table[index] 中;
存在數據,說明發生了hash沖突(存在二個節點key的hash值一樣), 繼續判斷key是否相等,相等,用新的value替換原數據(onlyIfAbsent為false);
如果不相等,判斷當前節點類型是不是樹型節點,如果是樹型節點,創建樹型節點插入紅黑樹中;(如果當前節點是樹型節點證明當前已經是紅黑樹了);
如果不是樹型節點,創建普通Node加入鏈表中;判斷鏈表長度是否大于 8并且數組長度是不是大于64,大于的話鏈表轉換為紅黑樹;
插入完成之后判斷當前節點數是否大于閾值,如果大于開始擴容為原數組的二倍。
以上7個步驟,不一定完全死記硬背,咱也背不下來,因此威哥的邏輯還是基于理解本質。
7.多線程情況下,調整 HashMap 的大小會有什么問題?
由于線程不安全的原因,在多線程條件下調整 HashMap 的大小時會存在多個 HashMap 對象的競爭關系,不知道要給哪一個調整大小。如此一來,多線程情況調整 HashMap 的大小就會陷入死循環的情況,在 Java1.5 以后就增加了 ConcurrentHashMap 的對象解決多線程等問題。
8.HashMap擴容機制是怎么樣的,JDK7 與JDK8有什么不同嗎?
首先,我們需要知道HashMap為什么需要擴容,道理很簡單,HashMap底層是用數組+鏈表實現的,而數組是預先就已經分配好內存的,如果需要對數組進行擴容,需要重新開辟一個新的數組再將舊數組上的元素進行轉移,如果不進行擴容,那么會導致HashMap的鏈表過長,查詢效率降低,所以需要對數組進行擴容。
在JDK7中,HashMap擴容的條件是 (size >= threshold) && (null !=table[bucketIndex]) , size 為HashMap當前的容量, threshold 初始化值為12, table[bucketIndex] 代表所put進來的key所對應的數組上的元素,所以在JDK7中擴容條件是當當Put操操作傳入的 作傳入的Key值所對應的數組位置上不為空時并且當前容量大于等于了擴容的閾值時才進行擴容 值所對應的數組位置上不為空時并且當前容量大于等于了擴容的閾值時才進行擴容,JDK7中的擴容思路是:開辟一個新的數組,數組大小為原數組的兩倍,然后再將數組上的鏈表與元素轉移到新數組上,此過程可能會出現死鎖。
JDK8中的擴容條件比JDK7中要少,只有當前容量大于等于了擴容的閾值時才進行擴容 當前容量大于等于了擴容的閾值時才進行擴容,并且擴容的思路也發生了變化,思路比較復雜。
以上就是“92%的同學都在搜索的hashmap面試題”,你能回答上來嗎?如果想要了解更多的Java面試題相關內容,可以關注動力節點Java官網。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習