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

Java基礎(chǔ)之淺談hashCode()和equals()

 更新時間:2021年06月20日 17:18:54   作者:java技術(shù)愛好者_(dá)R  
今天給大家?guī)淼氖顷P(guān)于Java基礎(chǔ)的相關(guān)知識,文章圍繞著hashCode()和equals()展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下

寫在前面

其實很早我就注意到阿里巴巴Java開發(fā)規(guī)范有一句話:只要重寫 equals,就必須重寫 hashCode。

我想很多人都會問為什么,所謂知其然知其所以然,對待知識不單止知道結(jié)論還得知道原因。

hashCode方法

hashCode()方法的作用是獲取哈希碼,返回的是一個int整數(shù)

學(xué)過數(shù)據(jù)結(jié)構(gòu)的都知道,哈希碼的作用是確定對象在哈希表的索引下標(biāo)。比如HashSet和HashMap就是使用了hashCode方法確定索引下標(biāo)。如果兩個對象返回的hashCode相同,就被稱為“哈希沖突”。

equals方法

equals()方法的作用很簡單,就是判斷兩個對象是否相等,equals()方法是定義在Object類中,而所有的類的父類都是Object,所以如果不重寫equals方法則會調(diào)用Object類的equals方法。

Object類的equals方法是用“”號進(jìn)行比較,在很多時候,因為號比較的是兩個對象的內(nèi)存地址而不是實際的值,所以不是很符合業(yè)務(wù)要求。所以很多時候我們需要重寫equals方法,去比較對象中每一個成員變量的值是否相等。

問題來了

重寫equals()方法就可以比較兩個對象是否相等,為什么還要重寫hashcode()方法呢?

因為HashSet、HashMap底層在添加元素時,會先判斷對象的hashCode是否相等,如果hashCode相等才會用equals()方法比較是否相等。換句話說,HashSet和HashMap在判斷兩個元素是否相等時,會先判斷hashCode,如果兩個對象的hashCode不同則必定不相等。

下面我們做一個試驗,有一個User類,只重寫equals()方法,然后放到Set集合中去重。

public class User {

    private String id;

    private String name;

    private Integer age;
    
    public User(String id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(id, user.id) &&
            Objects.equals(name, user.name) &&
            Objects.equals(age, user.age);
    }
    
    //getter、setter、toString方法
}

然后我們循環(huán)創(chuàng)建10個成員變量的值都是一樣的User對象,最后放到Set集合中去重。

public static void main(String[] args) {
    List<User> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        User user = new User("1", "張三", 18);
        list.add(user);
    }
    Set<User> set = new HashSet<>(list);
    for (User user : set) {
        System.out.println(user);
    }
    List<User> users = list.stream().distinct().collect(Collectors.toList());
    System.out.println(users);
}

按道理我們預(yù)期會去重,只剩下一個“張三”的user,但實際上因為沒有重寫hashCode方法,所以沒有去重。

接著我們在User類里面重寫一些hashCode方法再試試,其他不變。

public class User {
    //其他不變
    
    //重寫hashCode方法
    @Override
    public int hashCode() {
        return Objects.hash(id, name, age);
    }
}

再運行,結(jié)果正確。

究其原因在于HashSet會先判斷hashCode是否相等,如果hashCode不相等就直接認(rèn)為兩個對象不相等,不會再用equals()比較了。我們不妨看看重寫hashCode方法和不重寫hashCode方法的哈希碼。

這是不重寫hashCode方法的情況,每個user對象的哈希碼都不一樣,所以HashSet會認(rèn)為都不相等。

這是重寫hashCode方法的情況,因為是用對象所有的成員變量的值計算出的哈希碼,所以只要兩個對象的成員變量都是相等的,則生成的哈希碼是相同的。

那么有些人看到這里,就會問,如果兩個對象返回的哈希碼都是一樣的話,是不是就一定相等?

答案是不一定的,因為HashSet、HashMap判斷哈希碼相等后還會再用equals()方法判斷。

總而言之:

  • 哈希碼不相等,則兩個對象一定不相同。
  • 哈希碼相等,兩個對象不一定相同。
  • 兩個對象相同,則哈希碼和值都一定相等。

總結(jié)

所以回到開頭講的那句,只要重寫 equals,就必須重寫 hashCode,這是一個很重要的細(xì)節(jié),如果不注意的話,很容易發(fā)生業(yè)務(wù)上的錯誤。

特別是有時候我們明明用了HashSet,distinct()去重,但是就是不生效,這時應(yīng)該回頭看看重寫了equals()和hashCode()方法了嗎?

到此這篇關(guān)于Java基礎(chǔ)之淺談hashCode()和equals()的文章就介紹到這了,更多相關(guān)hashCode()和equals()內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java 批量獲取地址間距離工具(支持中轉(zhuǎn)站)

    Java 批量獲取地址間距離工具(支持中轉(zhuǎn)站)

    本文主要介紹了Java批量獲取地址間距離,獲取兩個地址間距離,實現(xiàn)方式比較多,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • Java編程中的equals方法使用全解

    Java編程中的equals方法使用全解

    這篇文章主要介紹了Java編程中的equals方法使用全解,是Java入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-10-10
  • java獲取優(yōu)酷視頻地址示例

    java獲取優(yōu)酷視頻地址示例

    使用JAVA解析優(yōu)酷視頻頁,得到視頻真實地址, 還可以下載,需要的朋友可以參考下
    2014-03-03
  • Spring Gateway自定義請求參數(shù)封裝的實現(xiàn)示例

    Spring Gateway自定義請求參數(shù)封裝的實現(xiàn)示例

    這篇文章主要介紹了Spring Gateway自定義請求參數(shù)封裝的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Java經(jīng)典排序算法之歸并排序?qū)崿F(xiàn)代碼

    Java經(jīng)典排序算法之歸并排序?qū)崿F(xiàn)代碼

    這篇文章主要介紹了Java經(jīng)典排序算法之歸并排序?qū)崿F(xiàn)代碼,歸并排序是建立在歸并操作上的一種有效的排序算法,該算法是采用分治法的一個非常典型的應(yīng)用,將已有序的子序列合并,得到完全有序的序列,需要的朋友可以參考下
    2023-10-10
  • springboot使用redis對單個對象進(jìn)行自動緩存更新刪除的實現(xiàn)

    springboot使用redis對單個對象進(jìn)行自動緩存更新刪除的實現(xiàn)

    本文主要介紹了springboot使用redis對單個對象進(jìn)行自動緩存更新刪除的實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • BaseDao封裝增刪改查的代碼詳解

    BaseDao封裝增刪改查的代碼詳解

    本篇文章主要介紹對數(shù)據(jù)庫中表中的數(shù)據(jù)進(jìn)行增改刪查詢,封裝一個工具類(BaseDao)的詳細(xì)使用以及部分理論知識,并通過代碼示例給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2024-03-03
  • springboot上傳文件并返回url過程

    springboot上傳文件并返回url過程

    這篇文章主要介紹了springboot上傳文件并返回url過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • Spring Boot線程池使用的一些實用心得

    Spring Boot線程池使用的一些實用心得

    理論上線程越多程序可能更快,但在實際使用中我們需要考慮到線程本身的創(chuàng)建以及銷毀的資源消耗,以及保護(hù)操作系統(tǒng)本身的目的我們通常需要將線程限制在一定的范圍之類,這篇文章主要給大家介紹了關(guān)于Spring Boot線程池使用的一些實用心得,需要的朋友可以參考下
    2021-09-09
  • Spring IOC中的Bean對象用法

    Spring IOC中的Bean對象用法

    這篇文章主要介紹了Spring IOC中的Bean對象用法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09

最新評論

陆良县| 钟山县| 耒阳市| 舟山市| 土默特左旗| 凤翔县| 晋江市| 武功县| 南京市| 德化县| 曲麻莱县| 建湖县| 巴青县| 区。| 磴口县| 衡东县| 渑池县| 广元市| 西乡县| 清水县| 扶余县| 南城县| 巴东县| 罗定市| 开封县| 枞阳县| 江城| 革吉县| 泸溪县| 佳木斯市| 平定县| 理塘县| 西青区| 新河县| 象山县| 遵义县| 东明县| 太仆寺旗| 沂水县| 邯郸市| 石台县|