為什麼重寫Equals方法要重寫HashCode方法

来源:https://www.cnblogs.com/yysbolg/archive/2023/07/29/17589252.html
-Advertisement-
Play Games

為什麼重寫Equals方法要重寫HashCode方法 1.Equals的作用和重寫Equals需要遵循的規則 Equals的主要作用是判斷兩個對相是否相等, Object類是所有類的父類,因此每個對象都可以使用Object的Equals相比較: public boolean equals(Objec ...


為什麼重寫Equals方法要重寫HashCode方法

1.Equals的作用和重寫Equals需要遵循的規則

Equals的主要作用是判斷兩個對相是否相等, Object類是所有類的父類,因此每個對象都可以使用Object的Equals相比較:

    public boolean equals(Object obj) {
        return (this == obj);
    }
  1. Object類中equals方法比較的是兩個對象的引用地址,只有對象的引用地址指向同一個地址時,才認為這兩個地址是相等的,否則這兩個對象就不想等。
  2. 如果有兩個對象,他們需要的是這兩個對象相等,因此預設的equals()方法是不符合我們的要求的,這個時候我們就需要對equals()方法進行重寫以滿足我們的預期結果。
  3. 在java的集合框架中需要用到equals()方法進行查找對象,如果集合中存放的是自定義類型,並且沒有重寫equals()方法,則會調用Object父類中的equals()方法按照地址比較,往往會出現錯誤的結果,此時我們應該根據業務需求重寫equals()方法。

重寫Equals方法需要遵循的規則

  1. 必須定義等價關係:自反、對稱、傳遞。自反性:對於任意的對象x,x.equals(x)返回true(自己一定等於自己);對稱性:對於任意的對象x和y,若x.equals(y)為true,則y.equals(x)亦為true;傳遞性:對於任意的對象x、y和z,若x.equals(y)為true且y.equals(z)也為true,則x.equals(z)亦為true;
  2. 除非對象被修改,否則調用多次equals應為同樣結果:對於任意的對象x和y,x.equals(y)的第一次調用為true,那麼x.equals(y)的第二次、第三次、第n次調用也均為true,前提條件是沒有修改x也沒有修改y;
  3. 對於非空引用x,x.equals(null)永遠返回為false。

2.重寫hashcode的原因及重寫hashCode()方法需要遵循的協定

1.什麼是hashcode

hashcode是一個數值,主要作用是散列數據的快速存儲, Object類是所有類的父類,因此每個對象都可以使用Object的hashcode()得到對應的hash值:

public native int hashCode();
  1. hashCode()方法用於散列數據的快速存儲,HashSet/HashMap/Hashtable類存儲數據時都是根據存儲對象的hashcode值來進行分類存儲的,一般先根據hashcode值在集合中進行分類,在根據equals()方法判斷對象是否相同。
  2. HashMap對象是根據其Key的hashCode來獲取對應的Value。
  3. 生成一個好的hashCode值能提高HashSet查找的性能,差的hashCode值不但不能提高性能,甚至可能造成錯誤。比如hashCode方法中返回常量,會讓,HashSet的查找效率退化為List集合的查找效率;hashCode方法中返回隨機數,會讓查找結果變的不可預測。
  4. 好的hashCode生成方式是讓對象中的關鍵屬性與質數相乘,並將積相加獲取。

2.重寫hashcode方法的原因:

  1. 為了維護hashCode()方法的equals協定,該協定指出:如果根據 equals()方法,兩個對象是相等的,那麼對這兩個對象中的每個對象調用 hashCode方法都必鬚生成相同的整數結果;而兩個hashCode()返回的結果相等,兩個對象的equals()方法不一定相等。
  2. HashMap對象是根據其Key的hashCode來獲取對應的Value。
  3. 在重寫父類的equals()方法時,也重寫hashcode()方法,使相等的兩個對象獲取的HashCode值也相等,這樣當此對象做Map類中的Key時,兩個equals為true的對象其獲取的value都是同一個,比較符合實際。

3.重寫hashCode()方法需要遵循的協定

  1. 一致性:在Java應用程式執行期間,在對同一對象多次調用hashCode方法時,必須一致地返回相同的整數,前提是將對象進行hashcode比較時所用的信息沒有被修改。
  2. equals:如果根據equals()方法比較,兩個對象是相等的,那麼對這兩個對象中的每個對象調用hashCode()方法都必鬚生成相同的整數結果,等價對象必須有相同的hashcode。註:這裡說的equals()方法是指Object類中未被子類重寫過的equals()方法。
  3. 如果根據equals()方法比較,兩個對象不相等,那麼對這兩個對象中的任一對象上調用hashCode方法不一定生成不同的整數結果。但是,程式員應該意識到,為不相等的對象生成不同整數結果可以提高哈希表的性能。

示例代碼

學生類: Student.java
package com.java.example;
import java.util.Objects;

public class Student {
    private int age;
    private String name;
    public Student(int age, String name) {
        this.age = age;
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        Student student = (Student) obj;
        return this.age == student.age && Objects.equals(this.age, student.age) && Objects.equals(this.name, student.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(this.age, this.name);
    }
}

 

測試類: EqualsAndHashcode.java
package com.java.example;
import java.util.HashSet;
public class EqualsAndHashcode {
    public static void main(String[] args) {
        Student student1=new Student(23,"李四");
        Student student2=new Student(23,"李四");
        System.out.println(student1==student2);
        System.out.println(student1.equals(student2));
        HashSet<Student> set=new HashSet<>();
        set.add(student1);
        set.add(student2);
        System.out.println(student1.hashCode());
        System.out.println(student2.hashCode());
        System.out.println(set.size());
    }
}
 
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ### [2023 年 7 月 28 日 22:16:06] ## ref 取 render 方式組件節點 一開始註意到組件 setup 和 render 一起使用的情況,好奇怎麼通過 ref 取到 render 中 jsx 里的節點,一開始試了以下的嘗試,結果是 undefined 的: ```j ...
  • # Mapbox—geocoder搜索地點error eaching the server [——There was an errorr eaching the server](#focus) 環境說明: vue3.3.4 mapbox-gl: 2.13.0 @mapbox/mapbox-gl-ge ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 前言 在Js中有一些比較冷門但是非常好用的方法,我在這裡稱之為高級方法,這些方法沒有被廣泛使用或多或少是因為存在一些相容性的問題,不是所有的瀏覽器都讀得懂的。這篇文章主要就是對這些方法做一個總結,有些方法在我們開發過程中有著重要的作用,我 ...
  • # VuePress@next 使用數學公式插件 搞了一個VuePress1.0的 現在升級了一下,但是使用數學公式的插件老報錯啊!經過不懈努力,終於搞定了。現在記錄一下。 ## VuePress 介紹 [VuePress](https://vuepress.github.io/zh) 是一個以 M ...
  • ### JSON [`parse()`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse): 以文本字元串形式接受 JSON 對象作為參數,並返回相應的對象。 [` ...
  • ![](https://img2023.cnblogs.com/blog/3076680/202307/3076680-20230725164759224-48972087.png) # 1. 控制請求數量 ## 1.1. 這個世界可以隨時摧毀我們的系統 ### 1.1.1. 要麼拒絕工作 ### ...
  • 系統設計藍圖指南 我們有時敏捷軟體開發過程,系統設計採用一張紙,如下圖供參考圖例DNS接上面, APP或用戶 請求與響應,分頁,過期頭,Gzip,冪等性設計負載均衡,API網關,訪問日誌,CDN,服務伸縮,通用扇出服務《系統設計藍圖指南》源文件PDF 在:鏈接:https://pan.baidu.c ...
  • 本文通過實際業務需求場景建模案例,為讀者提供一種業務模型向數據模型設計的方法論,用於指導實際開發中如何進行業務模型向數據模型轉化抽象,並對設計的數據模型可用性、擴展性提供了建議性思考 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...