目錄
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(),我們必須遵循如下規則:
- 對稱性:如果x.equals(y)返回是"true",那麼y.equals(x)也應該返回是"true"。
- 反射性:x.equals(x)必須返回是"true"。
- 類推性:如果x.equals(y)返回是"true",而且y.equals(z)返回是"true",那麼z.equals(x)也應該返回是"true"。
- 一致性:如果x.equals(y)返回是"true",只要x和y內容一直不變,不管你重複x.equals(y)多少次,返回都是"true"。
- 非空性,x.equals(null),永遠返回是"false";x.equals(和x不同類型的對象)永遠返回是"false"。
2.equals() 與 == 的區別
看完上面的內容,相信大家對equals()也有了一個初步的理解。
equals()它一般有兩種使用情況:
- 重寫了equals(),我們一般都會重寫equals(),用來判斷兩個對象之間的屬性值是否相等
- 未重寫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()的作用是獲取散列碼。但是,散列碼是用來幹什麼的呢?爲什麼散列表需要散列碼呢?要解決這些問題,就需要理解散列表!關於散列表的內容,非三言兩語道的明白;大家可以通過下面幾篇文章來學習:
爲了能理解後面的內容,這裏簡單的介紹一下散列碼的作用。
我們都知道,散列表存儲的是鍵值對(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()有可能相等,也有可能不等。