equals()、hashCode()和compareTo()方法

1.equals()、hashCode()和compareTo()方法

   一般來說,如果你要把一個類的對象放入容器中,那麼通常要爲其重寫equals()方法,讓他們比較地址值而不是內容值。特別地,如果要把你的類的對象放入散列中,那麼還要重寫hashCode()方法;要放到有序容器中,還要重寫compareTo()方法。

       有許多人學了很長時間的Java,但一直不明白hashCode方法的作用, 我來解釋一下吧。首先,想要明白hashCode的作用,你必須要先知道Java中的集合。總的來說,Java中的集合(Collection)有兩類,一類是List,再有一類是Set,其次是Map。你知道它們的區別嗎?List集合內的元素是有序的,元素可以重複;Set集合內的元素無序,但元素不可重複;Map是以key/value對的形式存儲。那麼這裏就有一個比較嚴重的問題了:要想保證元素不重複,可兩個元素是否重複應該依據什麼來判斷呢?這就是Object. equals ()方法了。但是,如果每增加一個元素就檢查一次,那麼當元素很多時,後添加到集合中的元素比較的次數就非常多了。也就是說,如果集合中現在已經有1000個元素,那麼第1001個元素加入集合時,它就要調用1000次equals()方法。這顯然會大大降低效率。於是,Java採用了哈希表的原理。哈希(Hash)實際上是個人名,由於他提出一哈希算法的概念,所以就以他的名字命名了. 

       希算法也稱爲散列算法,是將數據依特定算法直接指定到一個地址上。如果詳細講解哈希算法,那需要更多的文章篇幅,我在這裏就不介紹了。
      初學者可以這樣理解,hashCode方法實際上返回的就是對象存儲的物理地址(實際可能並不是)。這樣一來,當集合要添加新的元素時,先調用這個元素的hashCode方法,就一下子能定位到它應該放置的物理位置上。
    如果這個位置上沒有元素,它就可以直接存儲在這個位置上,不用再進行任何比較了;如果這個位置上已經有元素了,就調用它的equals方法與新元素進行比較,相同的話就不存了,不相同就散列其它的地址。即equals解決了hashCode值衝突的問題,這樣一來實際調用equals方法的次數就大大降低了,幾乎只需要一兩次。所以,Java對於eqauls方法和hashCode方法是這樣規定的:

(1)如果兩個對象相同,那麼它們的hashCode值一定要相同;

(2)如果兩個對象的hashCode相同,它們並不一定相同。

   上面說的對象相同指的是用eqauls方法比較。總體來說,hashCode方法得到一個代表對象的整數,這個整數在應用程序運行時保持不變。整數的意義類似於對象的身份證號碼,如String、包裝類、URL、File將本方法覆蓋,當對象代表的值相同時,得到的hashcode值相同。如果兩個集合對象所含有的對象引用都相同,則這兩個集合對象的hashcode值相同。

    當然你可以不按要求去做了,但你會發現,相同的對象可以出現在Set集合中。同時,增加新元素的效率會大大下降。

       hashCode這個方法是用來鑑定2個對象是否相等的。 那你會說,不是還有equals這個方法嗎? 不錯,這2個方法都是用來判斷2個對象是否相等的。但是他們是有區別的。 一般來講,equals這個方法是給用戶調用的,如果你想判斷2個對象是否相等,你可以重寫equals方法,然後在代碼中調用,就可以判斷他們是否相等 了。簡單來講,equals方法主要是用來判斷從表面上看或者從內容上看2個對象是不是相等。舉個例子,有個學生類,屬性只有姓名和性別,那麼我們可以 認爲只要姓名和性別相等,那麼就說這2個對象是相等的。              

       hashcode方法一般用戶不會去調用,比如在hashmap中,由於key是不可以重複的,他在判斷key是不是重複的時候就判斷了hashcode 這個方法,而且也用到了equals方法。這裏不可以重複是說equals和hashcode只要有一個不等就可以了!所以簡單來講,hashcode相 當於是一個對象的編碼,就好像文件中的md5,他和equals不同就在於他返回的是int型的,比較起來不直觀。我們一般在覆蓋equals的同時也要覆蓋hashcode,讓他們的邏輯一致。舉個例子,還是剛剛的例子,如果姓名和性別相等就算2個對象相等的話,那麼hashcode的方法也要返回姓名 的hashcode值加上性別的hashcode值,這樣從邏輯上,他們就一致了。要從物理上判斷2個對象是否相等,用==就可以了。


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章