Java 超詳細講解hashCode方法
1、介紹一下hashCode方法
hashCode()的作用是獲取哈希碼,也稱為散列碼,它實際上是返回一個int整數(shù)。這個哈希碼的作用是確定該對象在哈希表中的索引位置。hashCode()定義在JDK的Object.java中,這就意味著Java中的任何類都包含有hashCode()函數(shù)。- 散列表存儲的是鍵值對(key-value),它的特點是:能根據(jù)“鍵”快速的檢索出對應的“值”。這其中就利用到了散列碼!(可以快速找到所需要的對象)。
2、為什么需要hashCode方法?
在我們編寫程序的過程中,判斷兩個對象是否相同是十分常見且經(jīng)常面對的一個問題。而 hashCode() 方法就是用來提升比較兩個對象的速度的。
我們就以“HashSet 如何檢查重復”為例子來說明為什么要有 hashCode:
- 當你把對象加入
HashSet時,HashSet 會先計算對象的hashcode值來判斷對象加入的位置,同時也會與其他已經(jīng)加入的對象的hashcode值作比較,如果沒有相符的hashcode,HashSet會假設(shè)對象沒有重復出現(xiàn)。 - 但是如果發(fā)現(xiàn)有相同
hashcode值的對象,這時會調(diào)用 equals()方法來檢查hashcode相等的對象是否真的相同。如果兩者相同,HashSet就不會讓其加入操作成功。如果不同的話,就會重新散列到其他位置。 - 這樣我們就大大減少了
equals的次數(shù),相應就大大提高了執(zhí)行速度。
3、hashCode(),equals()兩種方法是什么關(guān)系?
Java 對于 eqauls() 方法和 hashCode() 方法是這樣規(guī)定的:
- 同一對象上多次調(diào)用 hashCode() 方法,總是返回相同的整型值。
- 如果 a.equals(b),則一定有 a.hashCode() 一定等于 b.hashCode()。
- 如果 !a.equals(b),則 a.hashCode() 不一定等于 b.hashCode()。此時如果 a.hashCode() 總是不等于 b.hashCode(),會提高 hashtables 的性能。
- a.hashCode()==b.hashCode() 則 a.equals(b) 可真可假
- a.hashCode()!= b.hashCode() 則 a.equals(b) 為假。
上面結(jié)論簡記:
- 如果兩個對象 equals,Java 運行時環(huán)境會認為他們的 hashCode 一定相等。
- 如果兩個對象不 equals,他們的 hashCode 有可能相等。
- 如果兩個對象 hashCode 相等,他們不一定 equals。
- 如果兩個對象 hashCode 不相等,他們一定不 equals。
4、為什么重寫 equals 方法必須重寫 hashcode 方法 ??
- 我們上面講解到 如果 兩個對象
equals的話,那么它們的hashCode值必然相等。如果只重寫了equals方法,而不重寫hashCode的方法,會造成hashCode的值不同,而equals方法判斷出來的結(jié)果為true。 - 在Java中的一些容器中,不允許有兩個完全相同的對象,插入的時候,如果判斷相同則會進行覆蓋。這時候如果只重寫了
equals的方法,而不重寫hashCode的方法,Object中hashCode是根據(jù)對象的存儲地址轉(zhuǎn)換而形成的一個哈希值。這時候就有可能因為沒有重寫hashCode方法,造成相同的對象散列到不同的位置而造成對象的不能覆蓋的問題。
例如
Dog類
package com.xiao;
/**
* @author :小肖
* @date :Created in 2022/3/11 14:42
*/
public class Dog {
private String name;
private Integer age;
public Dog() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Dog(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if(obj.getClass() != getClass()){
return false;
}
Dog dog = (Dog) obj;
if(dog.getAge() == age && dog.getName().equals(name)){
return true;
}
return false;
}
}
測試類
import com.xiao.Dog;
public class Test {
public static void main(String[] args) {
Dog dog = new Dog("小旺",2);
Dog dog1 = new Dog("小旺",2);
System.out.println("equals結(jié)果:" + dog.equals(dog1));
System.out.println("dog 的 hashCode 值是否等于 dog1 的 hashCode 值:" +(dog.hashCode() == dog1.hashCode()));
}
}
測試結(jié)果
equals結(jié)果:true
dog 的 hashCode 值是否等于 dog1 的 hashCode 值:false
到此這篇關(guān)于Java 超詳細講解hashCode方法的文章就介紹到這了,更多相關(guān)Java hashCode 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java的DataInputStream和DataOutputStream數(shù)據(jù)輸入輸出流
這里我們來看一下Java的DataInputStream和DataOutputStream數(shù)據(jù)輸入輸出流的使用示例,兩個類分別繼承于FilterInputStream和FilterOutputStream:2016-06-06
springboot之redis cache TTL選項的使用
這篇文章主要介紹了springboot之redis cache TTL選項的使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07
Lombok注解之@SuperBuilder--解決無法builder父類屬性問題
這篇文章主要介紹了Lombok注解之@SuperBuilder--解決無法builder父類屬性問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09

