hashmap value可以为空吗_美团面试题:Hashmap结构,1.7和1.8有哪些区别(最详细解析)...
作者|依本多情
原文:blog.csdn.net/qq_36520235/article/details/82417949
一、真實面試題之:Hashmap的結構,1.7和1.8有哪些區別
不同點:
(1)JDK1.7用的是頭插法,而JDK1.8及之后使用的都是尾插法,那么他們為什么要這樣做呢?因為JDK1.7是用單鏈表進行的縱向延伸,當采用頭插法時會容易出現逆序且環形鏈表死循環問題。但是在JDK1.8之后是因為加入了紅黑樹使用尾插法,能夠避免出現逆序且鏈表死循環的問題。
(2)擴容后數據存儲位置的計算方式也不一樣:
在JDK1.7的時候是直接用hash值和需要擴容的二進制數進行&(這里就是為什么擴容的時候為啥一定必須是2的多少次冪的原因所在,因為如果只有2的n次冪的情況時最后一位二進制數才一定是1,這樣能最大程度減少hash碰撞)(hash值 & length-1)。
而在JDK1.8的時候直接用了JDK1.7的時候計算的規律,也就是擴容前的原始位置+擴容的大小值=JDK1.8的計算方式,而不再是JDK1.7的那種異或的方法。但是這種方式就相當于只需要判斷Hash值的新增參與運算的位是0還是1就直接迅速計算出了擴容后的儲存方式。
在計算hash值的時候,JDK1.7用了9次擾動處理=4次位運算+5次異或,而JDK1.8只用了2次擾動處理=1次位運算+1次異或。
擴容流程對比圖:
(3)JDK1.7的時候使用的是數組+ 單鏈表的數據結構。但是在JDK1.8及之后時,使用的是數組+鏈表+紅黑樹的數據結構(當鏈表的深度達到8的時候,也就是默認閾值,就會自動擴容把鏈表轉成紅黑樹的數據結構來把時間復雜度從O(n)變成O(logN)提高了效率)。
這里再進行補充兩個問題:
(1)為什么在JDK1.7的時候是先進行擴容后進行插入,而在JDK1.8的時候則是先插入后進行擴容的呢?
//其實就是當這個Map中實際插入的鍵值對的值的大小如果大于這個默認的閾值的時候(初始是16*0.75=12)的時候才會觸發擴容,
//這個是在JDK1.8中的先插入后擴容
if?(++size?>?threshold)
????????????resize();
其實這個問題也是JDK8對HashMap中,主要是因為對鏈表轉為紅黑樹進行的優化,因為你插入這個節點的時候有可能是普通鏈表節點,也有可能是紅黑樹節點,但是為什么1.8之后HashMap變為先插入后擴容的原因,我也有點不是很理解?歡迎來討論這個問題?
但是在JDK1.7中的話,是先進行擴容后進行插入的,就是當你發現你插入的桶是不是為空,如果不為空說明存在值就發生了hash沖突,那么就必須得擴容,但是如果不發生Hash沖突的話,說明當前桶是空的(后面并沒有掛有鏈表),那就等到下一次發生Hash沖突的時候在進行擴容,但是當如果以后都沒有發生hash沖突產生,那么就不會進行擴容了,減少了一次無用擴容,也減少了內存的使用。
void?addEntry(int?hash,?K?key,?V?value,?int?bucketIndex)?{
????????//這里當錢數組如果大于等于12(假如)閾值的話,并且當前的數組的Entry數組還不能為空的時候就擴容
???? if?((size?>=?threshold)?&&?(null?!=?table[bucketIndex]))?{
?//擴容數組,比較耗時
??????? ?resize(2?*?table.length);
???????? hash?=?(null?!=?key)???hash(key)?:?0;
???????? bucketIndex?=?indexFor(hash,?table.length);
???? }
???? createEntry(hash,?key,?value,?bucketIndex);
}
?void?createEntry(int?hash,?K?key,?V?value,?int?bucketIndex)?{
???? Entry?e?=?table[bucketIndex];//把新加的放在原先在的前面,原先的是e,現在的是new,next指向e
??? ?table[bucketIndex]?=?new?Entry<>(hash,?key,?value,?e);//假設現在是new
???? size++;
}(2)為什么在JDK1.8中進行對HashMap優化的時候,把鏈表轉化為紅黑樹的閾值是8,而不是7或者不是20呢(面試蘑菇街問過)?
如果選擇6和8(如果鏈表小于等于6樹還原轉為鏈表,大于等于8轉為樹),中間有個差值7可以有效防止鏈表和樹頻繁轉換。假設一下,如果設計成鏈表個數超過8則鏈表轉換成樹結構,鏈表個數小于8則樹結構轉換成鏈表,如果一個HashMap不停的插入、刪除元素,鏈表個數在8左右徘徊,就會頻繁的發生樹轉鏈表、鏈表轉樹,效率會很低。
還有一點重要的就是由于treenodes的大小大約是常規節點的兩倍,因此我們僅在容器包含足夠的節點以保證使用時才使用它們,當它們變得太小(由于移除或調整大小)時,它們會被轉換回普通的node節點,容器中節點分布在hash桶中的頻率遵循泊松分布,桶的長度超過8的概率非常非常小。所以作者應該是根據概率統計而選擇了8作為閥值。
????//Java中解釋的原因
???*?Because?TreeNodes?are?about?twice?the?size?of?regular?nodes,?we
?????*?use?them?only?when?bins?contain?enough?nodes?to?warrant?use
?????*?(see?TREEIFY_THRESHOLD).?And?when?they?become?too?small?(due?to
?????*?removal?or?resizing)?they?are?converted?back?to?plain?bins.??In
?????*?usages?with?well-distributed?user?hashCodes,?tree?bins?are
?????*?rarely?used.??Ideally,?under?random?hashCodes,?the?frequency?of
?????*?nodes?in?bins?follows?a?Poisson?distribution
?????*?(http://en.wikipedia.org/wiki/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
?????*?more:?less?than?1?in?ten?million
二、哈希表如何解決Hash沖突?
三、為什么HashMap具備下述特點:鍵-值(key-value)都允許為空、線程不安全、不保證有序、存儲位置隨時間變化
四、為什么 HashMap 中 String、Integer 這樣的包裝類適合作為 key 鍵
五、HashMap 中的 key若 Object類型, 則需實現哪些方法?
【面試題專欄】
吃透這份pdf,面試阿里、騰訊、百度等一線大廠,順利拿下心儀offer!
全網最全Spring系列面試題129道(附答案解析)
2萬字Java并發編程面試題整理(含答案,建議收藏)
85道Java微服務面試題整理(助力2020面試)
【2020年大廠面試必備】JVM與性能調優知識點整理
2019年面試官最喜歡問的28道ZooKeeper面試題
2019年全網最熱門的123個Java并發面試題總結
全網最熱門的119個Spring問題,哪些你還不會?
2020面試還搞不懂MyBatis?看看這27道面試題!(含答案和思維導圖)
2020年去一線大廠面試先過SSM框架這一關!
Spring Cloud+Spring Boot高頻面試題解析
2019年常見的Linux面試題及答案解析,哪些你還不會?
2019年常見Elasticsearch面試題答案解析
18道kafka高頻面試題哪些你還不會?(含答案和思維導圖)
2019年12道RabbitMQ高頻面試題你都會了嗎?(含答案解析)
2019年Dubbo你掌握的如何?快看看這30道高頻面試題!
2019年228道Java中高級面試題(8),哪些你還不會?
?你在看嗎?
總結
以上是生活随笔為你收集整理的hashmap value可以为空吗_美团面试题:Hashmap结构,1.7和1.8有哪些区别(最详细解析)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 铁皮多少钱一平方啊?
- 下一篇: 用python做乘法口诀表_使用pyth