1. 程式人生 > >JAVA-初步認識-常用對象API(集合框架-哈希表2)

JAVA-初步認識-常用對象API(集合框架-哈希表2)

這就是 utl 自己 哈希沖突 定義 成員 存儲 位置 mage

一.

哈希表中判斷元素是否相同的方式到底是什麽?我們要探索一下。

剛才我們存儲ab的時候,表中已經有ab了。再往裏面存儲ab的時候,首先要放入算法中計算地址。一算完,這個地址是5,然後到表中去尋找,發現5的位置上已經有元素了。接下來就不往裏面存了麽?不一定,我們只能說這個位置上已經有元素了,不能保證這個元素是ab。我有兩個元素算出來的地址都是5,不能因此就判斷這個元素就是相同的。

技術分享圖片

舉例來看,ab和ba,這兩個字符串是不一樣的,通過哈希算法得到的結果是一致的。它們的位置一樣,但是內容是不相同的。

在哈希表中,必須不能有重復的,那涉及一個問題,哈希表是如何確定元素是重復的呢?光憑哈希算法的結果不完全準。先看值,後判斷。

不是說哈希值得出的結果相同,就是同一元素,畢竟是轉借了一個過程,通過這個過程得到的相同,和直接判定相同是兩回事。

如果哈希值都不相同,那就不存在第二步的判斷內容了。

技術分享圖片

現在講一下哈希表中特殊的東西,當哈希值相同時,內容不相同,那麽就需要存儲,這就是哈希沖突(哈希值一樣)。兩個對象一樣,但是哈希值不一樣。

這種情況不多,因為一般哈希算法比較復雜。

這種情況是有的,解決的措施不唯一,比如說順延。萬一順延到後面沒位置怎麽辦呢?將數組長度延長,或者串聯。

串聯比較有趣,位置是5,掛一個出來,如下圖所示。這種串聯它會繼續算它的位置,是基於5來算的。

技術分享圖片

體系中有很多方式來存儲這樣的元素,而這些元素本身也有自己的規則和位置。(不可能說,兩個哈希值一樣,內容不一樣,就直接覆蓋掉,沒有那麽理想化)

不用擔心,直接用算法來實現就可以了。

我們擔心是這件事情,如果我想在這個數組中去查詢到底有沒有ba,首先到算法中去計算,得到一個位置。算到這個位置後,就到這個位置上去尋找這個元素。

和它一樣嗎?先比較ab,發現不一樣,但是這個位置上不止一個元素,再往下找ba,發現有,這時候就不存了。這是它內部產生的規律,並 不沖突。

(其實我比較好奇,哈希沖突,尤其是這樣掛著的形式,在內存中是怎樣的體現形式?)

搞定完以後,現在回頭來說一下,如果我們想要搞定哈希表,往裏面存這樣的對象,我們要註意hashcode和equals方法,觀看原先的例子。

往哈希表中存儲的是字符串,在存儲的時候,就采用了hashcode方法。

技術分享圖片

我們來看一下字符串的hashcode方法是什麽樣的。找到String類,它本身就覆蓋了object類中的hashcode方法,這個方法定義了字符串中的哈希碼,或者說哈希算法,同時也覆蓋了object中的equals方法,定義了自己的判斷內容是否相同的依據。

技術分享圖片

技術分享圖片

接下來我們看一下,它到底是怎麽完成的。打開String的源碼,左側的outline是大綱視窗,這裏面列出了當前類裏面的所有成員,這樣尋找起來比較方便。

技術分享圖片

找到hashcode,下圖顯示的就是字符串哈希算法。它怎麽算的,不用管,它是根據字符串自身的特點來計算的。

技術分享圖片

技術分享圖片

這裏的value,其實是字符串對應的數組。

再看它的equals,它也是在判斷其中的每一位。體系本身已經做了hashcode和equals的定義。

技術分享圖片

到目前為止講述了這麽多,要說一件重要的事兒,往裏面存儲一些自定義對象。

JAVA-初步認識-常用對象API(集合框架-哈希表2)