1. 程式人生 > >java中重寫equals()方法的時候為什麼要重寫hashCode()方法?

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));
	}
}