在始祖巨人中我們條列出了所有Java物件都會繼承自Object類別的共同方法,這篇會提到其中的hashCode()與equals()這兩個方法如何在HashSet中被拿來運用。
若我們想要把數值或物件裝在一個東西之中,最常用的就是陣列(Array)了,不過除了陣列以外其實還有很多這種可以儲存數值或物件的東西,在Java中統稱為集合(Collection),集合底下有許多種的實作API供Java Programmer直接使用,這篇要來談的是HashSet。
HashSet是可以直接創建實例使用的類別,實作了Set介面。
Set的特性就是只能存在不重複的數值或物件,所以如果有一個陣列[1, 1, 2, 3],把他丟到一個Set時,這個Set只會存在[1, 2, 3]。
而既然Set是一個介面,就表示Java底下還有其他實作的Set類別可以用,例如TreeSet。每種Set類別都有其獨特的運作機制,視程式的情況來決定要使用哪種Set,而通常最常用的就是HashSet了。
HashSet不保證內容物的順序性,只確保了這裡面一定擁有不重複的數值或物件。那實際上是怎麼辦到的呢?就是利用了Object類別中的hashCode()與equals()這兩個方法。
在我們把東西加進HashSet後,HashSet會先做第一件事情:檢查我當前HashSet的元素中,有沒有和正要加進來的東西有同樣的HashCode,如果沒有的話,沒問題,就是直接加入到了HashSet成功;若有相同的HashCode...
就會做第二件事情:呼叫擁有相同HashCode物件的equals()方法,看回傳值是不是為false,false的話那一樣會把它加進HashSet之中;true的話,很抱歉,HashSet就不會把它加進來。
若我們再說的細一點,HashSet之中有個叫做Hash Bucket的資料結構,它就像是一個Map,有key以及key對應的value,Hash Code就是Hash Bucket的key,而value的部分就像是一個LinkedList,先前提到若是HashCode相同但是equals()方法又會回傳false,那就會在原本已存在元素的節點,next屬性上加入下一個節點,並放入新加入的元素。(若你看不懂這段,可以看看這篇)
看到這邊可能會對hash code與equals()的結果有些打結的狀況,其實大部分情況hash code一致的情形,equals()也會回傳true的,但在資料結構的規則中就會允許這樣的情況發生,而有這樣對應的處理。
以下幫大家做個小結: