最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

為何修改equals方法時還要重寫hashcode方法的原因分析

 更新時間:2021年06月09日 16:53:52   作者:$May$  
這篇文章主要介紹了為何修改equals方法時還要重寫hashcode方法的原因分析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

為何修改equals方法時還要重寫hashcode方法

雖然在實際開發(fā)中,我們已經(jīng)使用到散列集合(如HashMap),或也單獨(dú)學(xué)過散列(Hash)。

但是也會有很多人像我一樣,看到有些時候別人寫的pojo中有對對象內(nèi)hashcode函數(shù)做一個重寫,這就讓我重新思考為什么要這么做? 下面就讓我和你一起去探索一下吧!

Hash是什么?

Hash就是上文說到的散列,是把任意長度的輸入(又叫做預(yù)映射pre-image)通過散列算法變換成固定長度的輸出,該輸出就是散列值。它的理論時間復(fù)雜度是可以達(dá)到O(1),但一般來說,這個散列函數(shù)是極難設(shè)計的。說到散列值,就是通過散列函數(shù)轉(zhuǎn)化出來的:

如果兩個散列值是不一樣y(x1)!=y(x2),那么這兩個散列值的原始輸入一定是不一樣的。

如果兩個散列值出現(xiàn)了相等,那么并不代碼這兩個散列值的原始輸入一定是一樣的,可能是屬于哈希碰撞(不同關(guān)鍵字經(jīng)過散列變換結(jié)果是一樣的的現(xiàn)象);

對于哈希函數(shù)有哪些我也不再介紹,想了解可以直接去查散列函數(shù)的。

Hashcode作用

很多情況下我們也許都會用到hash表來做提高查詢效率,那么這個hash表是如何提高效率的?其實就是基于上面所說的散列函數(shù),根據(jù)設(shè)計的散列函數(shù),我們對于每一個關(guān)鍵字都有唯一的散列值,那么就能夠直接根據(jù)這個散列值直接就能找到元素在集合中的位置,從而獲得其值,這對于集合的一個個對象進(jìn)行比較來說,是提高了很多的。

在這里插入圖片描述

通過以上操作,我們很容易就能理解為啥散列技術(shù)在查詢的復(fù)雜度是能達(dá)到O(1).

但是一般來說java都會內(nèi)置了hashcode的實現(xiàn),那為什么在寫對象的時候,只要對equals進(jìn)行重寫,都推薦對hashcode進(jìn)行重寫呢?

看HashCode的常規(guī)協(xié)定:

在 Java 應(yīng)用程序執(zhí)行期間,在同一對象上多次調(diào)用 hashCode 方法時,必須一致地返回相同的整數(shù),前提是對象上 equals 比較中所用的信息沒有被修改。從某一應(yīng)用程序的一次執(zhí)行到同一應(yīng)用程序的另一次執(zhí)行,該整數(shù)無需保持一致。

如果根據(jù) equals(Object) 方法,兩個對象是相等的,那么在兩個對象中的每個對象上調(diào)用 hashCode 方法都必須生成相同的整數(shù)結(jié)果。

以下情況不 是必需的:

如果根據(jù) equals(java.lang.Object) 方法,兩個對象不相等,那么在兩個對象中的任一對象上調(diào)用 hashCode 方法必定會生成不同的整數(shù)結(jié)果。但是,程序員應(yīng)該知道,為不相等的對象生成不同整數(shù)結(jié)果可以提高哈希表的性能。

實際上,由 Object 類定義的 hashCode 方法確實會針對不同的對象返回不同的整數(shù)。(這一般是通過將該對象的內(nèi)部地址轉(zhuǎn)換成一個整數(shù)來實現(xiàn)的,但是 JavaTM 編程語言不需要這種實現(xiàn)技巧。)

當(dāng)equals方法被重寫時,通常有必要重寫 hashCode 方法,以維護(hù) hashCode 方法的常規(guī)協(xié)定,該協(xié)定聲明相等對象必須具有相等的哈希碼。

根據(jù)以上知道,java內(nèi)部的一個實現(xiàn)是以地址來的,如果對equals進(jìn)行重寫了,也就是對象你判斷相等時不再以java提供的方法,那么將來在使用hash表的時候,就會存在equals是相等的,但hashcode卻是不相等的!

所以建議:在修改equals的方法時,記得修改hashcode方法!!!

下面做個小例子

/**
 * @author: Kilig
 * @date: 2020/6/22 21:18
 * @description:
 */
public class User {
    private int id;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User)) return false;
        User user = (User) o;
        return getId() == user.getId();
    }
//    @Override
//    public int hashCode() {
//        return Objects.hash(getId());
//    }
}
public static void main(String[] args) {
        User a=new User();
        User b=new User();
        a.setId(1);
        b.setId(1);
        System.out.println(a.equals(b));
        System.out.println(a.hashCode() == b.hashCode());
    }

運(yùn)行結(jié)果

在這里插入圖片描述

嘗試將其放到set集合時

看到這結(jié)果顯然不是我們想要的,因為我兩個對象相等,其```hashcode也應(yīng)相等,然而結(jié)果卻是在不可重復(fù)的set集合中存了兩個對象,所以我們做一個改進(jìn),對User進(jìn)行重寫hashcode``方法。

  @Override
    public int hashCode() {
        return Objects.hash(getId()); //使用默認(rèn)的hash函數(shù)處理關(guān)鍵字,這里是ID,我們認(rèn)為Id相等的用戶其就是同一個用戶
    }

然后看看set的結(jié)果:

在這里插入圖片描述

的確符合我們預(yù)期結(jié)果。

基于以上的學(xué)習(xí),我們也基本了解為啥在修改equals方法時也要對hashcode進(jìn)行修改。

Java重寫equals()方法的步驟

Java語言規(guī)范要求equals方法具有下面的特性:

  1. 自反性:對于任何非空引用x,x.equals(x)應(yīng)該返回true
  2. 對稱性:對于任何引用x和y,當(dāng)且僅當(dāng)y.equals(x)返回true,x.equals(y)也應(yīng)該返回true
  3. 傳遞性:對于任何引用x和y和z,如果x.equal(y)返回true,y.equals(z)返回true,x.equals(z)也應(yīng)該返回true
  4. 一致性:如果x和y引用的對象沒有發(fā)生變化,反復(fù)調(diào)用x.equals(y)應(yīng)該返回同樣的結(jié)果
  5. 對于任意非空引用x,x.equals(null)應(yīng)該返回false

重寫equals()方法的步驟:

顯式參數(shù)命名為otherObject,稍后需要將它轉(zhuǎn)換成另一個叫做other的變量

檢測this與otherObject是否引用同一個對象

if (this == otherObject) 
    return true;

檢測otherObject是否為null,是則返回false

if (this == null) 
    return false;

比較this與otherObject是否屬于同一個類。如果equals的語義在每個子類中有所改變,就使用getClass檢測

if (getClass() != otherObject.getClass()) 
    return false;

如果所有的子類都擁有統(tǒng)一的語義,就使用instanceof檢測

if (!(otherObject instanceof ClassName)) 
    return false;

將otherObject轉(zhuǎn)換成相應(yīng)的類類型變量

ClassName other = (ClassName) otherObject

將other需要比較的域成員都進(jìn)行比較,只要有一個不同都返回false

需要注意的是,如果重新定義了equals()方法,就必須重新定義hashCode()方法,以便用戶可以將對象插入到散列表中。

equals()方法與hashCode()方法的定義必須保持一致,即如果equals()返回true,則2個對象的hashCode()必須具有相同的值。

重寫equals()方法中有提到,我們需要將要比較的域成員都進(jìn)行比較,那么我們在重寫hashCode()方法時可以將這些域成員的散列值組合起來,這樣就能保證它與equals()方法具有一致性了。

假設(shè)需被比較的域成員為field_1、field_2與field_3,那么我們可以編寫一下hashCode()方法:

public int hashCode() {
    return Objects.hash(field_1, field_2, field_3);
}

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Lombok的@Accessors使用說明

    Lombok的@Accessors使用說明

    這篇文章主要介紹了Lombok的@Accessors使用說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • Java通過BCrypt加密過程詳解

    Java通過BCrypt加密過程詳解

    這篇文章主要介紹了Java通過BCrypt加密過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-07-07
  • idea+ springboot熱部署的配置方法

    idea+ springboot熱部署的配置方法

    這篇文章主要介紹了idea+ springboot熱部署的配置方法,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-05-05
  • logback的ShutdownHook關(guān)閉原理解析

    logback的ShutdownHook關(guān)閉原理解析

    這篇文章主要為大家介紹了logback的ShutdownHook關(guān)閉原理源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • Java從內(nèi)存角度帶你理解數(shù)組名實質(zhì)是個地址的論述

    Java從內(nèi)存角度帶你理解數(shù)組名實質(zhì)是個地址的論述

    這篇文章主要介紹了Java如何從內(nèi)存解析的角度理解“數(shù)組名實質(zhì)是一個地址”,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-09-09
  • java、php、C#、asp實現(xiàn)短信群發(fā)功能的方法

    java、php、C#、asp實現(xiàn)短信群發(fā)功能的方法

    這篇文章主要介紹了java、php、C#、asp實現(xiàn)短信群發(fā)功能的方法,以實例形式較為詳細(xì)的分析了java及php、C#、asp、VB.NET等調(diào)用短信發(fā)送接口進(jìn)行短信發(fā)送的功能,需要的朋友可以參考下
    2015-02-02
  • 妙解Java中的回調(diào)機(jī)制(CallBack)

    妙解Java中的回調(diào)機(jī)制(CallBack)

    本文以最簡明扼要的例子將Java的回調(diào)機(jī)制介紹給大家,感興趣的朋友可以參考一下。
    2016-07-07
  • springboot使用Validator校驗方式

    springboot使用Validator校驗方式

    這篇文章主要介紹了springboot使用Validator校驗方式,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2018-01-01
  • SpringBoot 自動配置失效的解決方法

    SpringBoot 自動配置失效的解決方法

    本文主要介紹了SpringBoot 自動配置失效的解決方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • mybatis嵌套循環(huán)map方式(高級用法)

    mybatis嵌套循環(huán)map方式(高級用法)

    這篇文章主要介紹了mybatis嵌套循環(huán)map方式(高級用法),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01

最新評論

永川市| 乌海市| 西华县| 樟树市| 子洲县| 连江县| 民乐县| 宜阳县| 禄丰县| 招远市| 涿州市| 砀山县| 文成县| 锦屏县| 抚宁县| 五寨县| 大悟县| 南汇区| 元谋县| 长子县| 康乐县| 杨浦区| 无为县| 唐海县| 鄂尔多斯市| 金寨县| 武安市| 丹巴县| 清新县| 克拉玛依市| 馆陶县| 武义县| 柳河县| 平顶山市| 凤山县| 冕宁县| 新沂市| 利辛县| 三亚市| 五大连池市| 玉林市|