java中重寫equals()方法的時候為什麼要重寫hashCode()方法?
有時候,或許會聽到被人說,在重寫equals方法的時候,記得重寫hashcode方法。那麼自然有這樣的疑問,那麼為什麼這樣?equals方法和hashCode方法是什麼關係?不重寫的時候會有什麼危害?文章將從一下幾個方面進行敘述。
一:什麼是hashCode(),equals()方法?
二:hashCode(),equals()兩種方法是什麼關係?
三:為什麼在重寫equals方法的時候要重寫hashcode的方法?
四:怎麼重寫這兩種方法?
一:什麼是hashCode(),equals()方法?
關於equals()方法,經常說的就是比較的是內容(與==比較的地址相對),這麼說不完全對--看下面這段程式碼:
學生類:
public class Student {
private int id;
private String name;
public Student(int id, String name) {
super();
this.id = id;
this.name = name;
}
}
主測試類:
public class Test { public static void main(String[] args) { Student s1=new Student(001,"邵小二"); Student s2=new Student(001,"邵小二"); System.out.println(s1.equals(s2)); } }
我們想通過一個學生的學號以及姓名來判斷是否是同一個學生。可是 根據程式的執行結果(打印出的為false)來看,即使是學號與姓名兩個欄位都完全的相同,判斷出的學生也不是相同的。
equals()在java.lang.Object下,其原始碼為:
public boolean equals(Object obj) {
return (this == obj);
}
即在Object中equals方法只是判斷的為是否為同一個物件的引用。
在String類中,我們可以這樣寫,列印的結果為true。
String str1="123"; String str2="123"; //print true System.out.println(str1.equals(str2));
這裡是因為在String類中對equals方法進行了重寫的原因。
什麼是hashcode方法?在java中,對物件的儲存採取了儲存在雜湊表中處理方法,hashcode方法是根據物件的地址轉換之後返回的一個雜湊值,其詳細的用法在這篇文章涉及的時候詳細的介紹過-點選開啟連結
二:hashCode(),equals()兩種方法是什麼關係?
要弄清楚這兩種方法的關係,就需要對雜湊表有一個基本的認識。其基本的結構如下:
對於hashcode方法,會返回一個雜湊值,雜湊值對陣列的長度取餘後會確定一個儲存的下標位置,如圖中用陣列括起來的第一列。
不同的雜湊值取餘之後的結果可能是相同的摸著時候就用equals方法判斷是否為相同的物件,不同則在連結串列中插入。
則有:
hashcode不相同,用equals()方法判斷的返回的一定為false。
hashcode相同,equals()方法返回值不能確認,可能為true,可能為false。
三:為什麼在重寫equals方法的時候要重寫hashcode的方法?
上述了兩種方法的關係之後,我們知道判斷的時候先根據hashcode進行的判斷,相同的情況下再根據equals()方法進行判斷。如果只重寫了equals方法,而不重寫hashcode的方法,會造成hashcode的值不同,而equals()方法判斷出來的結果為true。
在Java中的一些容器中,不允許有兩個完全相同的物件,插入的時候,如果判斷相同則會進行覆蓋。這時候如果只重寫了equals()的方法,而不重寫hashcode的方法,Object中hashcode是根據物件的儲存地址轉換而形成的一個雜湊值。這時候就有可能因為沒有重寫hashcode方法,造成相同的物件雜湊到不同的位置而造成物件的不能覆蓋的問題。
四:怎麼重寫這兩種方法?
關於重寫equals()方法應該滿足的原則,這裡就不在贅述。只是通過一個小例子來對其有一個重寫兩個方法有一個新的認識。
public class SimpleDemo {
// 部門
private String department;
// 工號
private int id;
public SimpleDemo(int id, String department) {
super();
this.id = id;
this.department = department;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getdepartment() {
return department;
}
public void setdepartment(String department) {
this.department = department;
}
@Override
public int hashCode() {
int hash = 1;
hash = hash * 17 + id;
hash = hash * 31 + department.hashCode();
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (obj == this)
return true;
if (obj instanceof SimpleDemo) {
SimpleDemo sd = (SimpleDemo) obj;
return sd.department.equals(department) && sd.id == id;
}
return false;
}
主測試方法類:
public class Test02 {
public static void main(String[] args) {
SimpleDemo sdo1=new SimpleDemo(0106,"技術部");
SimpleDemo sdo2=new SimpleDemo(0106,"技術部");
//print true
System.out.println(sdo1.equals(sdo2));
}
}