天天看點

為什麼重寫equals必須重寫hashCode的基礎分析

為什麼重寫equals必須重寫hashCode的基礎分析

1.我們先來了解下原生的equals和hashCode代碼

  原生equals:它判斷的是兩個對象是否相等

  原生hashCode值:它是根據記憶體位址換算出來的一個整數類型的值

2.至于為什麼要重寫equals和hashCode?

  當然為了滿足我們具體的業務需求啦,畢竟我們不一定隻比較對象相等嘛

3.做一個超簡單小案例來了解下(包名不規範,切勿模仿);

(1)建立一個Student類,不重寫equals和hashCode

package 重寫equal必須重寫hashcode;

public class Student {
	public String id; //學生的id
	public String name; //學生的名字
	
	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}
	
	public String toString() {
		return id + ":" + name;
	}
	
	public Student(String id, String name) {
		super();
		this.id = id;
		this.name = name;
	}
	
}
      

  (2)new一個hashSet,分别添加三個student

package 重寫equal必須重寫hashcode;

import java.util.HashSet;

public class Test {
	
	//學生ID和姓名都相同我們視為重複
	public static void main(String[] args) {
		HashSet hs = new HashSet();
		hs.add(new Student("001","小明"));
		hs.add(new Student("002","小花"));
		hs.add(new Student("002","小花"));
		System.out.println(hs);
	}
}
      

  (3)運作結果如下:

為什麼重寫equals必須重寫hashCode的基礎分析

 (4)我們可以看到,資訊出現了重複;new的對象不同生成的hashCode值不同,是以hashSet會把三個Student對象當作不同的對象。

2.接下來我們重寫equals而不重寫hashCode

(1)重寫equals後代碼如下:

package 重寫equal必須重寫hashcode;

public class Student {
	public String id; //學生的id
	public String name; //學生的名字
	
	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}
	
	public String toString() {
		return id + ":" + name;
	}
	
	public Student(String id, String name) {
		super();
		this.id = id;
		this.name = name;
	}
	
	public boolean equals(Object obj) {
		if(this == obj) {  //判斷是否是同一對象
			return true;	//同一類型傳回true(跟自己比較)
		}
		if(getClass()!=obj.getClass()) {   //判斷是否為同一類型
			return false;  //不是同類型傳回false(類型不同肯定為不同的對象)
		}
		Student stu = (Student)obj; //強制轉換成Student類型
		boolean result = this.id.equals(stu.id); //判斷ID是否相等
		return result; //傳回判斷結果
	}
}
      

 (2)現在我們運作下,結果如下圖:

為什麼重寫equals必須重寫hashCode的基礎分析

(3)可以發現重複的資訊沒有删除掉,可以判斷添加Student對象沒有調用equals方法,而是根據hashCode值的不同,hashSet就認為三個對象不相等。

3.最後我們重寫equals和hashCode;

(1)重寫hashCode;

package 重寫equal必須重寫hashcode;

public class Student {
	public String id; //學生的id
	public String name; //學生的名字
	
	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}
	
	public String toString() {
		return id + ":" + name;
	}
	
	public Student(String id, String name) {
		super();
		this.id = id;
		this.name = name;
	}
	
	public boolean equals(Object obj) {
		if(this == obj) {  //判斷是否是同一對象
			return true;	//同一類型傳回true(跟自己比較)
		}
		if(getClass()!=obj.getClass()) {   //判斷是否為同一類型
			return false;  //不是同類型傳回false(類型不同肯定為不同的對象)
		}
		Student stu = (Student)obj; //強制轉換成Student類型
		boolean result = this.id.equals(stu.id); //判斷ID是否相等
		return result; //傳回判斷結果
	}
	
	public int hashCode() { //重寫hashCode
		return id.hashCode();  //傳回ID屬性的哈希值
	}
}
      

 (2)運作結果如下:

為什麼重寫equals必須重寫hashCode的基礎分析

 (3)是不是就把重複的資訊移除了呢?哈哈

如果有不妥之處,請各位大佬多多包涵,這些也是個人的了解

如果你有補充,歡迎留下你的意見在評論區!