1. 程式人生 > 其它 >關於hashCode()和equals(),看這一篇就夠了!

關於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裡是不允許有重複元素的,這才是我們想要的效果。