關於hashCode()和equals(),看這一篇就夠了!
技術標籤:Java基礎及重難點java字串objecthashcode
我們經常被問到hashCode()方法和equals()方法的用法,以及什麼時候需要重寫這兩個方法的類似問題,本文是我對這兩個方法的一些理解。
一、equals()和"=="
提到equals()和"==",我們首先來理解一下它們的聯絡與區別。對於基本資料型別,==比較的是兩邊的值,對於引用型別,比較的是兩個物件的地址是否相等。
equals()用來比較兩個物件是否相等,如果我們不重寫equals方法的話,用的是Object類裡的equals(),它也是用==來比較兩邊的地址的。
public boolean equals(Object obj) {
return (this == obj);
}
String類就重寫了equals(),用來比較字串是否相等,而不是直接比較它們的地址。
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
可以看到重寫後的方法首先判斷兩字串的地址,然後再比較字元陣列是否相同,因為String的底層就是就是一個用final修飾的字元陣列嘛。
這裡的instance關鍵字用來判斷方法傳入的物件是否為String例項,如果不是也就沒有必要進行下面的比較了。
二、equals()和hashCode()
我們經常說,重寫equals()要重寫hashCode(),不過,只有在需要將物件存入散列表結構的時候,才需要這樣做,例如HashMap,HashSet等。
在這種情況下:
1、equal()為true的兩個物件的hashcode值一定相等
2、hashcode值相同的兩個物件不一定相等
以HashSet為例,如果我們不只重寫equals卻不重寫hashCode,會產生什麼後果。
User類:
package test;
import java.util.Objects;
public class User {
String name;
int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return age == user.age && Objects.equals(name, user.name);
}
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
測試:
public class Test {
public static void main(String[] args) {
Set set = new HashSet();
User user1 = new User("kun",18);
User user2 = new User("kun",18);
set.add(user1);
set.add(user2);
System.out.println("user1 hashcode:"+user1.hashCode());
System.out.println("user2 hashcode:"+user2.hashCode());
System.out.println("Set:"+set.toString());
System.out.println(user1.equals(user2));
}
}
結果:
可以看到我們的set裡儲存了重複的物件,因為它們的hashcode值不同,set把它們看作不同的物件了,但是呼叫equals()返回的是true。
下面我們重寫一下hashCode(),就用下面比較簡單的寫法:
@Override
public int hashCode() {
int nameCode = name.hashCode();
return nameCode^age;
}
再次執行上面的測試程式碼:
可以看到,Set裡是不允許有重複元素的,這才是我們想要的效果。