標籤:完成 對比 情況 記憶體位址 1.7 ring key 效能 TE
要想知道一個元素是否在數組或鏈表中,只能從前向後挨個對比,無論是數組還是鏈表,其對資料的查詢表現都比較無力。在的二叉排序樹中,還會將資料排序以進行二分尋找,將時間複雜度從O(n)降低到O(lg n)。
出現這個問題的根源在於,我們沒有辦法直接根據一個元素找到它儲存的位置。
那有沒有辦法消除這個對比的過程呢?雜湊表就是解決查詢問題的一種方案。
什麼是雜湊表與Hash函數
通俗來講,雜湊表就是通過關鍵字來擷取資料的一種資料結構,它通過把關鍵字映射為表中的位置來擷取元素,這種映射主要是使用Hash函數。
因為不同需求需要的key類型不一致,可能是int,可能是String,也可能是其他任意對象。但是記憶體位址卻不能以這些對象來定址,因而Hash函數的作用就是把這些對象通過合理的方式轉為int類型,從而完成資料的儲存。Hash函數需要保證的是對於相同的key,其計算結果總是相同的。
這個過程就好比我們用拼音查字典。如果要查一個字,我們不會從第一頁到最後一頁挨著看,這將需要很長的時間,而是根據其發音先在拼音表中找到對應的頁數,直接定位到對應的頁即可。當然,由於有許多發音一致的漢字,所以我們可能依然需要逐個對比,但這複雜度就小太多了。
雜湊表的過程就和上述例子一致,我們根據元素的key,通過hash函數直接定位其位置。然而類似於許多漢字的發音一致一樣,也會有許多的key通過hash函數定位的結果一致,這就是發生了所謂的雜湊碰撞。
解決雜湊碰撞的方法
比較通用的方法,就是使用數組+鏈表組合的方式。當出現雜湊碰撞時,在該位置的資料就通過鏈表的方式連結起來,:
在JDK1.7及之前的版本中,HashMap的儲存結構和是一致的,在JDK1.8之後還加入了紅/黑樹狀結構以進一步最佳化。
雜湊表的優缺點
雜湊表是一種最佳化儲存的思想,具體儲存元素的依然是其他的資料結構。
設計良好的雜湊表,能同時兼備數組和鏈表的優點,它能在插入和尋找時都具備良好的效能。
設計不好的雜湊表,有可能會出現較多的雜湊碰撞,導致鏈表過長,從而雜湊表會更像一個鏈表。還有當資料量很大時,為防止鏈表過長,就需要對數組進行擴容,這時就涉及到了數組的拷貝,其對效能的影響也很嚴重。
所以需要提前對可能的情況有良好的預測,才能真正發揮雜湊表的優勢。
源碼:Java集合源碼之:雜湊表(二)