????????面試core java,HashMap的結構差不多是必問題了。字面意思,真的真的是必問題了。
? ? ? ? 我遇到的問題有:
??????????1. HashMap, ConcurrentHashMap,HashTable 的結構,在JDK 1.7 和1.8 中有什么不同(最基礎)
? ? ? ? ? ?2. put時,是加到鏈表頭還是鏈表尾
? ? ? ? ? ?3. get的時間復雜度(對鏈表,對紅黑樹)
????????然后,在一次糟心的面試中,面試官問問題1 ,我回答了,提到了loadfactor = 0.75, 對方來了句“這個都記,背得挺熟的嘛” , 我:???(黑人問號臉)。?
????????他問,那你說,為什么是0.75 , 不是0.5或者1?
????????這個好回答。 如果是0.5 , 那么每次達到容量的一半就進行擴容,默認容量是16, 達到8就擴容成32,達到16就擴容成64, 最終使用空間和未使用空間的差值會逐漸增加,空間利用率低下。 ?如果是1,那意味著每次空間使用完畢才擴容,在一定程度上會增加put時候的時間。
????????接著,他問我為什么是0.75,不是0.6或者0.8?
? ? ? ? 我:……?
========================
? ? ? ? 面試只是檢測知識的一個經歷。 回頭再想想:那為什么是0.75呢? 0.75是 0.5 ~ 1的中間值??(寫到這里,突然想這樣解釋也可以哎,取中間值)
? ? ? ? 然后我去查看了API...
? ? ? ? JDK 1.7中:
As a general rule, the default load factor (.75) offers a good tradeoff between time and space costs. Higher values decrease the space overhead but increase the lookup cost (reflected in most of the operations of the HashMap class, including get and put). The expected number of entries in the map and its load factor should be taken into account when setting its initial capacity, so as to minimize the number of rehash operations. If the initial capacity is greater than the maximum number of entries divided by the load factor, no rehash operations will ever occur.
翻譯過來就是:
作為一般規則,默認負載因子(0.75)在時間和空間成本上提供了很好的折衷。較高的值會降低空間開銷,但提高查找成本(體現在大多數的HashMap類的操作,包括get和put)。設置初始大小時,應該考慮預計的entry數在map及其負載系數,并且盡量減少rehash操作的次數。如果初始容量大于最大條目數除以負載因子,rehash操作將不會發生。
? ? JDK 1.8中也有上述內容,并且還有一段如下(現在頭腦清醒了,覺得下面這段與“為什么是0.75”關系不大,不過是百度中能找到的關于這個問題的別人的文章中有著一段):
Ideally, under random hashCodes, the frequency of nodes in bins follows a Poisson distribution with a parameter of about 0.5 on average for the default resizing threshold of 0.75, although with a large variance because of resizing granularity. Ignoring variance, the expected occurrences of list size k are (exp(-0.5) pow(0.5, k) / factorial(k)). The first values are:
? ? ? 0:? ? 0.60653066
? ? ? 1:? ? 0.30326533
? ? ? 2:? ? 0.07581633
? ? ? 3:? ? 0.01263606
? ? ? 4:? ? 0.00157952
? ? ? 5:? ? 0.00015795
? ? ? 6:? ? 0.00001316
? ? ? 7:? ? 0.00000094
? ? ? 8:? ? 0.00000006
簡單翻譯一下,就是 :
理想狀態下,在隨機哈希值的情況,對于loadfactor = 0.75 ,雖然由于粒度調整會產生較大的方差,桶中的Node的分布頻率服從參數為0.5的泊松分布。?
(泊松分布算是我在這個沒什么意思的探討中學到的新的知識點吧,比較通俗易懂的解釋在這里 )
在上面給出的結果中,t=1,λ=0.5,推算得各種結果。這個我自己寫程序實現了一下,沒錯。但這個地方跟0.75沒關系,實際上是在JDK1.8中,如果鏈表的長度大于8,那么鏈表轉為紅黑樹 這個操作得來的。
那么,回到問題,0.75是怎么得來的呢?StackOverFlow上有這么一個回答我覺得可以給我結案了:
原鏈接如下:What is the significance of load factor in HashMap?
這個回答的釋義是: 一個bucket空和非空的概率為0.5,通過牛頓二項式等數學計算,得到這個loadfactor的值為log(2),約等于0.693. 同回答者所說,可能小于0.75 大于等于log(2)的factor都能提供更好的性能,0.75這個數說不定是 pulled out of a hat。
==========================
昨天和我學金融的著重號朋友討論這個問題,最后她說
其實我就是不喜歡面試官陰陽怪氣地說一句“這都背下來了”,你說你考我問題,又覺得我是背的,那你期待我怎么表現??回答不上來?哎,過去就過去了。
總結一下:
為什么是0.75? 這個我沒找到一個肯定完整的答案,這個問題比較偏,問到的幾率很小。但經過探討,你可以回答
1. 取 0.5和1 的缺點是什么, 同時說一下上面第一段引用的JDK API,就說API中也沒有說為什么取0.75.
2. 對方如果是個杠精,你可以深入理解一下stackoverflow中的這個計算,然后告訴他。 如果對方考你高數……我也沒辦法了,記得來我這里領一個愛的抱抱。
============================
學到了什么:?
1. 泊松分布和指數分布,順便回想一下正態分布
2. 氣場不和的面試官要用正確的心態去面對。