Java 超詳細(xì)講解hashCode方法
1、介紹一下hashCode方法
hashCode()
的作用是獲取哈希碼,也稱為散列碼,它實(shí)際上是返回一個int整數(shù)。這個哈希碼的作用是確定該對象在哈希表中的索引位置。hashCode()
定義在JDK的Object.java中,這就意味著Java中的任何類都包含有hashCode()
函數(shù)。- 散列表存儲的是鍵值對(key-value),它的特點(diǎn)是:能根據(jù)“鍵”快速的檢索出對應(yīng)的“值”。這其中就利用到了散列碼?。梢钥焖僬业剿枰膶ο螅?。
2、為什么需要hashCode方法?
在我們編寫程序的過程中,判斷兩個對象是否相同是十分常見且經(jīng)常面對的一個問題。而 hashCode()
方法就是用來提升比較兩個對象的速度的。
我們就以“HashSet 如何檢查重復(fù)”為例子來說明為什么要有 hashCode:
- 當(dāng)你把對象加入
HashSet
時,HashSet 會先計(jì)算對象的hashcode
值來判斷對象加入的位置,同時也會與其他已經(jīng)加入的對象的hashcode
值作比較,如果沒有相符的hashcode
,HashSet
會假設(shè)對象沒有重復(fù)出現(xiàn)。 - 但是如果發(fā)現(xiàn)有相同
hashcode
值的對象,這時會調(diào)用 equals()方法來檢查hashcode
相等的對象是否真的相同。如果兩者相同,HashSet
就不會讓其加入操作成功。如果不同的話,就會重新散列到其他位置。 - 這樣我們就大大減少了
equals
的次數(shù),相應(yīng)就大大提高了執(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 運(yùn)行時環(huán)境會認(rèn)為他們的 hashCode 一定相等。
- 如果兩個對象不 equals,他們的 hashCode 有可能相等。
- 如果兩個對象 hashCode 相等,他們不一定 equals。
- 如果兩個對象 hashCode 不相等,他們一定不 equals。
4、為什么重寫 equals 方法必須重寫 hashcode 方法 ??
- 我們上面講解到 如果 兩個對象
equals
的話,那么它們的hashCode
值必然相等。如果只重寫了equals
方法,而不重寫hashCode
的方法,會造成hashCode
的值不同,而equals
方法判斷出來的結(jié)果為true
。 - 在Java中的一些容器中,不允許有兩個完全相同的對象,插入的時候,如果判斷相同則會進(jìn)行覆蓋。這時候如果只重寫了
equals
的方法,而不重寫hashCode
的方法,Object中hashCode
是根據(jù)對象的存儲地址轉(zhuǎn)換而形成的一個哈希值。這時候就有可能因?yà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 超詳細(xì)講解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-06springboot之redis cache TTL選項(xiàng)的使用
這篇文章主要介紹了springboot之redis cache TTL選項(xiàng)的使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07Java中try-catch的使用及注意細(xì)節(jié)
現(xiàn)在有很多的語言都支持try-catch,比如常見的就是c++,java等,這篇文章主要給大家介紹了關(guān)于Java中try-catch的使用及注意細(xì)節(jié)的相關(guān)資料,文中通過圖文以及實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-06-06Lombok注解之@SuperBuilder--解決無法builder父類屬性問題
這篇文章主要介紹了Lombok注解之@SuperBuilder--解決無法builder父類屬性問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09