日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

稀疏多项式的运算用链表_用最简单的大白话聊一聊面试必问的HashMap原理和部分源码解析...

發布時間:2023/12/19 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 稀疏多项式的运算用链表_用最简单的大白话聊一聊面试必问的HashMap原理和部分源码解析... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

HashMap在面試中經常會被問到,一定會問到它的存儲結構和實現原理,甚至可能還會問到一些源碼

今天就來看一下HashMap

首先得看一下HashMap的存儲結構和底層實現原理

如上圖所示,HashMap底層是用數組+鏈表+紅黑樹實現的,其中紅黑樹是JDK1.8對HashMap優化之后加入的,當鏈表的長度大于8的時候會由鏈表結構轉為紅黑樹,這些等下在看源碼分析的時候都可以看到具體的實現。

那為什么用這幾種數據結構來實現?

這種結構在數據結構上稱為散列鏈表,其中的數組就相當于一個一個的桶(Bucket),當有數據準備存進去的時候,它會通過一定的散列算法去計算,盡可能的讓數據平均的命中到各個桶上面去,盡可能的避免哈希碰撞。如果發生哈希碰撞,就是不同的數據最后落到了同一個桶上的時候,就采用鏈表的方式來存儲,但是鏈表長度比較長了的時候,去存儲數據,讀取數據都需要不停的去遍歷循環,所以此時再采用鏈表結構的話效率會明顯下降,所以JDK1.8之后做了優化,當鏈表的長度大于8的時候就由鏈表轉為紅黑樹來存儲。紅黑樹是平衡二叉樹的其中一種實現,它比普通的二叉樹表現更優異,因為普通的查詢二叉樹在一定條件下也可能會變成鏈表結構,而紅黑樹它是平衡二叉樹的一種,它是通過左旋右旋變色等保持樹的平衡。

簡單的了解了HashMap的存儲結構后,下面來講下HashMap其中三個方法的源碼

一、hash()方法

static

這個方法里看似簡單,卻暗藏玄機。

它是拿到了key本身的hashCode后,又做了一次運算,先將原來的hashCode無符號右位移16位,然后再將原來的hashCode異或(^)上這個位移后的值,最后得到一個值。

補充知識:

>> 表示右移,如果該數為正,則高位補0,若為負數,則高位補1。

>>>表示無符號右移,也叫邏輯右移,即若該數為正,則高位補0,而若該數為負數,則右移后高位同樣補0。

^ 表示異或運算,每個位相同為0,不同為1

比如:

0 ^ 1 得 1
1 ^ 1 得 0
0 ^ 0 得 0
1 ^ 0 得 1

那為什么要無符號右移16位后做異或運算?key本身的hashCode直接拿來用不好嗎?

我們做一個簡單演練

將h無符號右移16為相當于將高區16位移動到了低區的16位,再與原hashcode做異或運算,可以將高低位二進制特征混合起來

從上文可知高區的16位與原hashcode相比沒有發生變化,低區的16位發生了變化

我們可知通過上面(h = key.hashCode()) ^ (h >>> 16)進行運算可以把高區與低區的二進制特征混合到低區,那么為什么要這么做呢?

我們都知道重新計算出的新哈希值在后面將會參與hashmap中數組槽位的計算,計算公式:(n - 1) & hash,假如這時數組槽位有16個,則槽位計算如下:

仔細觀察上文不難發現,高區的16位很有可能會被數組槽位數的二進制碼鎖屏蔽,如果我們不做剛才移位異或運算,那么在計算槽位時將丟失高區特征

也許你可能會說,即使丟失了高區特征不同hashcode也可以計算出不同的槽位來,但是細想當兩個哈希碼很接近時,那么這高區的一點點差異就可能導致一次哈希碰撞,所以這也是將性能做到極致的一種體現

使用異或運算的原因

異或運算能更好的保留各部分的特征,如果采用&運算計算出來的值會向1靠攏,采用|運算計算出來的值會向0靠攏

為什么槽位數必須使用2^n

1、為了讓哈希后的結果更加均勻

這個原因我們繼續用上面的例子來說明

假如槽位數不是16,而是17,則槽位計算公式變成:(17 - 1) & hash

從上文可以看出,計算結果將會大大趨同,hashcode參加&運算后被更多位的0屏蔽,計算結果只剩下兩種0和16,這對于hashmap來說是一種災難

2、可以通過位運算e.hash & (newCap - 1)來計算,a % (2^n) 等價于 a & (2^n - 1) ,位運算的運算效率高于算術運算,原因是算術運算還是會被轉化為位運算

說了這么多點,上面提到的所有問題,最終目的還是為了讓哈希后的結果更均勻的分部,減少哈希碰撞,提升hashmap的運行效率

二、put()方法

public

這個沒什么好講的,調用了下邊的putVal()方法

三、putVal()方法

這個方法很重要,是往hashMap里put值的核心邏輯,下邊源碼里的每一行我都進行了注釋

/**

hashMap中還有其他的一些方法在此就不挨個來說了

可以在下方進行評論,一起學習進步~


作者:嗑嗑磕嗑瓜子的貓
鏈接:https://blog.csdn.net/ju_362204801/article/details/104776452?utm_medium=distribute.pc_category.none-task-blog-hot-1.nonecase&depth_1-utm_source=distribute.pc_category.none-task-blog-hot-1.nonecase&request_id=
來源:CSDN

總結

以上是生活随笔為你收集整理的稀疏多项式的运算用链表_用最简单的大白话聊一聊面试必问的HashMap原理和部分源码解析...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。