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