溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

java中equals和hashCode的作用是什么

發(fā)布時間:2021-07-19 09:46:10 來源:億速云 閱讀:164 作者:chen 欄目:大數(shù)據(jù)

這篇文章主要講解了“java中equals和hashCode的作用是什么”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“java中equals和hashCode的作用是什么”吧!


 
equals

什么時候覆蓋equals方法我就不再說了,相信熟悉Java的讀者肯定都知道,我們著重聊一下如何書寫規(guī)范的equls方法。因為一個不規(guī)范的equals方法將會造成集合無法表現(xiàn)出預(yù)期的行為。

重寫equals方法需要保證equals滿足以下特性:

  • 自反性:對于任何非null的引用值x,必須滿足x.equals(x)返回true
  • 對稱性:對于任何非null的引用值x和y,當(dāng)且僅當(dāng)y.equals(x)返回true時,x.equals(y)必須返回true
  • 傳遞性:對于任何非null的引用值x、y、z,如果x.equals(y)返回true并且y.equals(z)返回true時,那么x.equals(z)也必須返回true
  • 一致性:對于任何非null的引用值x、y,只要equals涉及的字段信息沒有被修改,多次調(diào)用x.equals(y)要返回一樣的結(jié)果
  • 非空性:對于任何非null的引用值x,x.equals(null)必須返回false
 
自反性

該要求說明對象必須等于自身,如果違背這一條你會發(fā)下集合的contains方法無法告訴你正確的結(jié)果。

 
對稱性

對稱性要求兩個對象對于它們是否相等要保持一致,下面這段代碼違反了對稱性

public class IgnoreCaseString {
   private final String s;
   public IgnoreCaseString(String s) {        this.s = s;    }
   @Override    public boolean equals(Object obj) {        if (obj instanceof IgnoreCaseString) {            return s.equalsIgnoreCase(((IgnoreCaseString) obj).s);        }        if (obj instanceof String) {            return s.equalsIgnoreCase((String) obj);        }        return false;    }
   public static void main(String[] args) {        IgnoreCaseString ignoreCaseString = new IgnoreCaseString("Phone");        String string = "phone";        System.out.println(ignoreCaseString.equals(string));        System.out.println(string.equals(ignoreCaseString));        System.out.println("------------------------------");        List<String> list = new ArrayList<>();        list.add(string);        System.out.println(list.contains(ignoreCaseString));    }}
 
 
傳遞性

這種情況通常發(fā)生在具有父子關(guān)系的對象中,子類增加的信息會影響到equals的比較結(jié)果。解決這種問題通常有兩種方式,一種是通過getClass()的方式(具體的大家可以通過閱讀Effective Java這本書),還有一種是在我們擴(kuò)展類的功能時盡量使用復(fù)合而并不是使用繼承,通過復(fù)合組件里面的域的比較也可以解決。

 
一致性

一致性要求如果兩個對象相等,那么他們就必須保持相等,除非它們中有對象被修改了。

 
非空性

非空性要求所有的對象不等于null

 
如何寫好equals
  1. 如果比較操作昂貴,可以優(yōu)先使用==操作符檢查是否是同一個對象引用
  2. 使用instanceOf操作符檢查參數(shù)是否為正確的類型(正確的類型通常是指equals方法所在的那個類,但有時也是該類實現(xiàn)的某個接口,比如Set、List等集合)
  3. 把參數(shù)轉(zhuǎn)換為正確的類型
  4. 對于該類中的每個關(guān)鍵字段,檢查參數(shù)中的字段是否與該對象中對應(yīng)的字段相匹配,對于既不是float也不是double類型的基本類型域,可以使用==操作符進(jìn)行比較,對于引用類型可以遞歸調(diào)用equals方法,對于float使用Float.compare方法,double使用Double.compare方法,數(shù)組域可以使用Arrays.equals方法。
  5. 最最重要的一步,當(dāng)編寫完equals方法一定要進(jìn)行單元測試,驗證equals方法是否滿足上述特性。
 
hashCode

在每個覆蓋了equals方法的類中,必須重寫hashCode方法。如果不這樣做,會導(dǎo)致該類無法與所有基于散列的集合一起正常運(yùn)作。hashCode方法需要遵循以下規(guī)定:

  • 在程序執(zhí)行期間,只要對象的equals方法比較操作用到的信息沒有被修改,那么對于同一個對象調(diào)用多次hashCode方法必須返回同一個整數(shù)。但是在一個應(yīng)用程序的多次執(zhí)行中,每次執(zhí)行可以返回的整數(shù)可以不一致。
  • 如果兩個對象的根據(jù)equals方法比較結(jié)果是相等的,那么調(diào)用任意一個對象的hashCode方法都必須產(chǎn)生相同的結(jié)果
  • 如果兩個對象根據(jù)equals方法比較結(jié)果不想等,那么調(diào)用這兩個對象的hashCode方法可以產(chǎn)生相同或者不同的整數(shù)結(jié)果,但是盡量保證程序可以產(chǎn)出不同的整數(shù)因為這樣可以提高散列表的性能
 
如何寫好hashCode
  1. 把某個非零的常數(shù)值,比如說17保存在一個result的int類型變量中
  2. 對于對象中equals方法中涉及到的每一個域(f)計算散列碼
  3. 按照result = 31 * result + c(第二步計算的散列碼)合并到result中并返回
  4. 驗證自己的hashCode方法

使用非0初始值的原因是讓域初始值為0的那些域可以影響到散列值,如果使用0那么散列值不會再受這些域的影響,從而增加Hash沖突的可能性,從而降低了散列表的性能

31是一個奇素數(shù),在Java中如果兩個比較大的數(shù)相乘則會發(fā)生移除,31并不算一個比較大的數(shù),其次選用31的理由是可以用移位和減法來代替乘法,31 * i = (i << 5) - i,現(xiàn)在的VM都可以自動完成這種優(yōu)化,因此可以獲得很好的性能提升

 
計算散列碼
  • 如果f是boolean類型,計算f? 1 :0
  • 如果f是byte、char、short或者int類型,計算(int)f
  • 如果是long類型,計算(int)(f ^ (f>>>32))
  • 如果是float類型,計算Float.floatToIntBits(f)
  • 如果是double類型,計算Double.doubleToLongBits(f),然后在將得到long結(jié)果計算散列值
  • 如果是一個引用類型,遞歸調(diào)用hashCode
  • 如果是是一個數(shù)組,調(diào)用Arryas.hashCode方法

如果一個類是不可變的并且計算散列碼的成本比較大,可以考慮把散列碼緩存在對象內(nèi)部,而不是每次請求時都重新計算(這一點在Kafka中也有所應(yīng)用)。

感謝各位的閱讀,以上就是“java中equals和hashCode的作用是什么”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對java中equals和hashCode的作用是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI