重寫前:java
* ==表示兩個對象的內存地址 * equals()也表示對象內存地址 * hashCode()表示該對象在JVM中的32位內存地址
重寫後:
==仍表示兩個對象的內存地址 equals()表示連個對象的值是否相等,相等就視爲同一個對象 若是equals()方法重寫,那麼hashCode()方法也要重寫,由於要保證同一個對象的hashCode值相等這樣的規定。
根據javaAPI文檔上的介紹:程序員
(1)、同一個對象的hashCode值必定相同,不管是否重寫過equals()方法,也就是說重寫過之後他們的值相等了,那麼他們的hashCode也要保持相等,因此就也要重寫hashCode()方法。算法
(2)、若是兩個對象不相等,那麼對這兩個對象中的任一對象上調用 hashCode 方法不 要求必定生成不一樣的整數結果。可是,程序員應該意識到,爲不相等的對象生成不一樣整數結果能夠提升哈希表的性能。ide
好比重寫後的hashCode方法以下:性能
@Override測試
public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + sex; return result; }
比較兩個對象是否相等:this
(1)先比較連個對象的hashCode值是否相等,若是相等則比較(2)(由於不一樣的對象也有可能hashCode值相等),若是不等則必定不是同一個對象code
(2)再比較equals()方法,若是相等則視爲贊成對象,反之則不是同一個對象。**對象
二、hashCode()和equals()關係是什麼?
明白幾個原則:
equals相等的兩個對象,hashcode必定相等。
equals不相等的兩個對象,hashcode不必定不相等。
hashcode不相等,那麼equals是必定不等的。
hashcode相等,equals可能相等,也可能不等。
解釋下第四個原則:
就比如hashcode像是一個詞典目錄裏的按字母爲索引查找字,查一個「Z」拼音開頭的詞,下面等查到「本身」,「自我」,「知道」等詞,用equals就是判斷這些詞語當中是否有相等的詞,「本身」和「知道」兩個詞不相等的,因此equals值不等,但它們同屬於"Z"開頭的詞因此它們hashcode值相等。索引
三、爲何重寫equals的同時也要重寫hashCode呢?
hash算法是爲了提升equals比較的效率而被髮明出來的。這點在集合方面就能體現出來,就好比在List或Set集合裏要比較是否有重複元素,當發現某個集合對象與另外一個集合對象equals比較的結果相等時,則中止查找返回true值,反之,返回false值。
但若是集合中有大量元素呢,假設一個集合A裏有10萬元素,並且另外一個比較的對象B中還可能沒有重複的值,則意味着其實不用比較我都知道二者不相同,但程序依然會對集合A裏遍歷10萬元素而後和B進行逐一排查。。。又或者當我要加入第100001個數據我要驗證前面元素有重複值,就要跟前面10萬個元素一一比較,效率可想而知很低。
而哈希算法就是Java系統首先調用對象的hashCode()方法得到該對象的哈希碼錶,而後根據哈希碼找到相應的存儲區域,若哈希碼相同在取得該存儲區域內的每一個元素與該對象進行equals方法比較,若不一樣也就沒有繼續比較的必要了,這對於數量較大的狀況效率就提升了很多,重寫hashcode方法,最主要就是保證操做的元素在同一個對象裏且值都沒有重複,若沒有重寫hashcode,可能會出現將對象引用不一樣,但元素徹底相同的集合進行操做。
下面寫一個例子
package demo;
public class override_HshCode_Equals {
public int x;
public int y;
public override_HshCode_Equals(int x, int y) { this.x = x; this.y = y; } @Override public int hashCode() { //下面變量初始化值能夠任意取 final int prime = 31; int result = 1; result = prime * result + x; result = prime * result + y; return result; } /** * equals返回false就說明沒有重複項能夠添加 * true是重複不能添加 */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final override_HshCode_Equals heClass = (override_HshCode_Equals) obj; //這裏就對實例化對象裏的x,y進行比較 if (x != heClass.x) { return false; } if (y != heClass.y) { return false; } return true; }
}
測試類
package demo; import java.util.HashSet; public class TestMain { public static void main(String[] args) { HashSet<override_HshCode_Equals> set = new HashSet<override_HshCode_Equals>(); override_HshCode_Equals heClass1 = new override_HshCode_Equals(1, 1); override_HshCode_Equals heClass2 = new override_HshCode_Equals(5, 5); override_HshCode_Equals heClass3 = new override_HshCode_Equals(1, 1); set.add(heClass1); set.add(heClass2); set.add(heClass3); set.add(heClass1); System.out.println("set數量=" + set.size()); } } 結果以下 set數量=2
注:重寫override_HshCode_Equals類的hashCode至關於自定義返回了一個「哈希碼」,對比x,y值是否相等,先比較hashcode值,heClass1(3,3)==heClass3(3,3),因此它們的hashcode值相等,可是heClass2的x,y和heClass1,heClass3的x,y值不等,因此hashcode不等,equals必定不等,因此heClass2對象是能夠add進去的。前面說了heClass1和heClass3的hashcode值相等,而後進入equals進行對比,發現二者的對象都是相同的,根據程序add循序來看,因此heClass1是能夠add進去的,而後heClass3和後面add(heClass1)都爲重複項,就不會添加