爲什麼重新定義equals方法,就必須要重新定義hashCode方法?

原文鏈接:https://blog.csdn.net/pzxwhc/article/details/38047909

版權聲明:本文爲CSDN博主「Sauron1」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/pzxwhc/article/details/38047909

 

一.概述(怎麼判斷對象相等,hashCode作用)

       在Java中,判斷兩個對象是否相等,先判斷兩個對象的hashcode是否相等,如果hashcode不等,那麼認爲這兩個對象也不相等;如果相等,那麼判斷兩個對象用equals是否相等,如果相等,認爲兩個對象也相等,否則認爲兩個對象不等。

      Object中的hashcode方法在我們創建對象的時候爲每個對象計算一個散列碼。自己定義的類也可以重寫 hashcode,按照自己的方法計算散列碼。(重寫時簡單的返回一個int值也可以,但是一般需要根據你的業務邏輯重寫hashcode方法)

       數據結構有一種爲了提高查找的效率而存在的數據結構——散列表,散列表其實是普通數組概念的推廣,因爲可以對數組進行直接尋址,故可以再O(1)時 間內訪問數組的任意元素。hashcode方法的作用,它就是用來提高效率的,有句話說得好:爲速度而散列。因爲散列的Set和Map是基於 hashcode方法來查找對象的,所以你在使用這些類的時候一定要覆蓋hashcode方法,而非散列的Set和Map,例如 TreeSet,TreeMap等,它們只需equals方法就可以唯一確定對象的身份。

二.不使用hashCode會產生的問題

       Java中的集合(Collection)有兩類,一類是List,再有一類是Set。前者集合內的元素是有序的,元素可以重複;後者元素無序,但元素不 可重複。 那麼這裏就有一個比較嚴重的問題了:要想保證元素不重複,可兩個元素是否重複應該依據什麼來判斷呢? 這就是Object.equals方法 了。但是,如果每增加一個元素就檢查一次,那麼當元素很多時,後添加到集合中的元素比較的次數就非常多了。 也就是說,如果集合中現在已經有1000個元 素,那麼第1001個元素加入集合時,它就要調用1000次equals方法。這顯然會大大降低效率。

三.利用hashCode解決上述問題

       Java採用了哈希表的原理。哈希(Hash)實際上是個人名,由於他提出一哈希算法的概念,所以就以他的名字命名了。 哈希算法也稱爲散列算法,是將數據依特定算法直接指定到一個地址上。

       初學者可以這樣理解,hashCode方法實際上返回的就是對象存儲的物理地址(實際可能並不是)。這樣一來,當集合要添加新的元素時,先調用這個元素的 hashCode方法,就一下子能定位到它應該放置的物理位置上。如果這個位置上沒有元素,它就可以直接存儲在這個位置上,不用再進行任何比較了;如果這 個位置上已經有元素了,就調用它的equals方法與新元素進行比較(這裏注意,爲什麼相同了還要比較呢,是因爲不同的對象可能有相同的地址)相同的話就 不存了,不相同就散列其它的地址。所以這裏存在一個衝突解決的問題。這樣一來實際調用equals方法的次數就大大降低了,幾乎只需要一兩次。

四.需要注意的地方:

Java對於eqauls方法和hashCode方法是這樣規定的: 
1。如果兩個對象相同,那麼它們的hashCode值一定要相同;

2。如果兩個對象的 hashCode相同,它們並不一定相同    上面說的對象相同指的是用eqauls方法比較。  


五. Equals和hashcode的關係

 1. 對於良好的編程風格而言,你應該在重寫equals()方法的同時,也重寫hashCode()方法。

        如果你的對象想放進散列存儲的集合中(比如:HashSet,LinkedHashSet)或者想作爲散列Map(例如:HashMap,LinkedHashMap等等)的Key時,在重寫equals()方法的同時,必須重寫hashCode()方法。 

2. Jdk爲什麼希望我們在重寫equals方法時,非常有必要重寫hashcode方法。Hashcode是用於散列數據的快速存取,如利用 HashSet/HashMap/HashTable類來存儲數據時,都是根據存儲對象的hashcode值來判斷是否相同。如果我們對一個對象重寫了 equals方法,意思是隻要對象的成員變量的值相等那麼equals就返回true,但不重寫hashcode方法,那麼我們再new一個新的對象的時 候,當原對象.equals(新對象)等於true的時候,兩者的hashcode值是不相等的。由此產生了理解上的不一致,比如在存儲散列集合(如 Set類)的時候,將會存儲了兩個一樣的對象,導致混淆,因此,也就必須重寫hashcode方法。爲了保證這種一致性,必須滿足兩個條件:

      1. 當obj1.equals(obj2)的時候。Obj1.hashCode()== obj2.hashCode() 必須爲true。

      2. 當 obj1.hashcode() ==obj2.hashcode()爲false的時候,obj1.equals(obj2)也必須爲false。

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