你知道equals()與hashcode()之間的關係嗎?

1.equals()的作用是什麼?

定義在Object.java中的它,是根據判斷兩個對象之間的地址來判斷兩個對象是否相等,即等同於“==”。但我們通常會對它進行重寫。

1.1重寫equals()方法

代碼:

package com.hbk.util;

/**
 * @ProjectName: wxhospital
 * @Package: com.hbk.util
 * @ClassName: EqualsDemo1
 * @Author: Sarah0429
 * @Description: 重寫equals(),用來比較值是否相等
 * @Date: 2020/04/28 14:10
 * @Version: 1.0
 */

public class EqualsDemo1 {

    public static void main(String[] args) {
        Person puyuma1 = new Person("puyuma", 1);
        Person puyuma2 = new Person("puyuma", 1);
        System.out.println(puyuma1.equals(puyuma2));
    }

    private static class Person {
        String name;
        int sex;

        public Person(String name, int sex) {
            this.name = name;
            this.sex = sex;
        }

        public String toString() {
            return name + " - " + sex;
        }

        /**
         * 重寫equals()
         */
        @Override
        public boolean equals(Object obj) {
            //判斷傳入對象是否爲空
            if (obj == null) {
                return false;
            }

            //根據兩個對象的地址判斷是否爲同一對象
            if (this == obj) {
                return true;
            }

            //判斷兩個對象的類型是否相同
            if (this.getClass() != obj.getClass()) {
                return false;
            }

            Person person = (Person) obj;
            return name.equals(person.name) && sex == person.sex;
        }
    }
}

控制檯打印:
在這裏插入圖片描述
由上可以看出,當我們重寫了equals()時,它的作用是:當兩個person的name與sex屬性值相同時,返回true。

1.2不重寫equals()方法

代碼:

package com.hbk.util;

/**
 * @ProjectName: wxhospital
 * @Package: com.hbk.util
 * @ClassName: EqualsDemo1
 * @Author: Sarah0429
 * @Description: 重寫equals(),用來比較值是否相等
 * @Date: 2020/04/28 14:10
 * @Version: 1.0
 */

public class EqualsDemo1 {

    public static void main(String[] args) {
        Person puyuma1 = new Person("puyuma", 1);
        Person puyuma2 = new Person("puyuma", 1);
        System.out.println(puyuma1.equals(puyuma2));
    }

    private static class Person {
        String name;
        int sex;

        public Person(String name, int sex) {
            this.name = name;
            this.sex = sex;
        }

        public String toString() {
            return name + " - " + sex;
        }

    }
}

控制檯打印:
在這裏插入圖片描述

由上可以看出,當我們未重寫equals()時,它調用的是==,即判斷是否爲同一對象,而不是比較裏面的具體內容。

1.3對於equals(),我們必須遵循如下規則:

  1. 對稱性:如果x.equals(y)返回是"true",那麼y.equals(x)也應該返回是"true"。
  2. 反射性:x.equals(x)必須返回是"true"。
  3. 類推性:如果x.equals(y)返回是"true",而且y.equals(z)返回是"true",那麼z.equals(x)也應該返回是"true"。
  4. 一致性:如果x.equals(y)返回是"true",只要x和y內容一直不變,不管你重複x.equals(y)多少次,返回都是"true"。
  5. 非空性,x.equals(null),永遠返回是"false";x.equals(和x不同類型的對象)永遠返回是"false"。

2.equals() 與 == 的區別

看完上面的內容,相信大家對equals()也有了一個初步的理解。
equals()它一般有兩種使用情況:

  1. 重寫了equals(),我們一般都會重寫equals(),用來判斷兩個對象之間的屬性值是否相等
  2. 未重寫equals(),即調用Object.java裏的equals(),等同於“==”

3.hashCode() 的作用是什麼?

它的作用是獲取哈希碼,也稱爲散列碼,是一個int整數。這個哈希碼的作用是確定該對象在哈希表中的索引位置。

hashCode() 定義在JDK的Object.java中,這就意味着Java中的任何類都包含有hashCode() 函數。
雖然,每個Java類都包含hashCode() 函數。但是,僅僅當創建並某個“類的散列表”(關於“散列表”見下面說明)時,該類的hashCode() 纔有用(作用是:確定該類的每一個對象在散列表中的位置;其它情況下(例如,創建類的單個對象,或者創建類的對象數組等等),類的hashCode() 沒有作用。
上面的散列表,指的是:Java集合中本質是散列表的類,如HashMap,Hashtable,HashSet。

也就是說:hashCode() 在散列表中才有用,在其它情況下沒用。 在散列表中hashCode() 的作用是獲取對象的散列碼,進而確定該對象在散列表中的位置。

OK!至此,我們搞清楚了:hashCode()的作用是獲取散列碼。但是,散列碼是用來幹什麼的呢?爲什麼散列表需要散列碼呢?要解決這些問題,就需要理解散列表!關於散列表的內容,非三言兩語道的明白;大家可以通過下面幾篇文章來學習:

[轉載] 散列表(Hash Table)從理論到實用(上)

[轉載] 散列表(Hash Table)從理論到實用(中)

[轉載] 散列表(Hash Table)從理論到實用(下) 

爲了能理解後面的內容,這裏簡單的介紹一下散列碼的作用。

我們都知道,散列表存儲的是鍵值對(key-value),它的特點是:能根據“鍵”快速的檢索出對應的“值”。這其中就利用到了散列碼!
散列表的本質是通過數組實現的。當我們要獲取散列表中的某個“值”時,實際上是要獲取數組中的某個位置的元素。而數組的位置,就是通過“鍵”來獲取的;更進一步說,數組的位置,是通過“鍵”對應的散列碼計算得到的。
下面,我們以HashSet爲例,來深入說明hashCode()的作用。

假設,HashSet中已經有1000個元素。當插入第1001個元素時,需要怎麼處理?因爲HashSet是Set集合,它不允許有重複元素。
“將第1001個元素逐個的和前面1000個元素進行比較”?顯然,這個效率是相當低下的。散列表很好的解決了這個問題,它根據元素的散列碼計算出元素在散列表中的位置,然後將元素插入該位置即可。對於相同的元素,自然是隻保存了一個。

由此可知,若兩個元素相等,它們的散列碼一定相等;但反過來確不一定。在散列表中,
1、如果兩個對象相等,那麼它們的hashCode()值一定要相同;
2、如果兩個對象hashCode()相等,它們並不一定相等。
注意:這是在散列表中的情況。在非散列表中一定如此!

3.1對於hashCode(),我們應該遵循如下規則:

1.在一個應用程序執行期間,如果一個對象的equals方法做比較所用到的信息沒有被修改的話,則對該對象調用hashCode方法多次,它必須始終如一地返回同一個整數。
2.如果兩個對象根據equals(Object o)方法是相等的,則調用這兩個對象中任一對象的hashCode方法必須產生相同的整數結果。
3.如果兩個對象根據equals(Object o)方法是不相等的,則調用這兩個對象中任一個對象的hashCode方法,不要求產生不同的整數結果。但如果能不同,則可能提高散列表的性能。

4.兩者之間的關係

兩句話概括:

  • 如果equals()返回“true”,那麼兩個對象的hashCode()必須相等。
  • 如果equals()返回“false”,那麼兩個對象的hashCode()有可能相等,也有可能不等。

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章