欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中equals和hashcode用法

 更新時間:2025年01月08日 09:38:22   作者:mikey棒棒棒  
`equals`和`hashCode`方法在Java中密切相關(guān),必須保持一致性,如果兩個對象通過`equals`方法相等,它們的`hashCode`也必須相同,這對于基于哈希的數(shù)據(jù)結(jié)構(gòu)至關(guān)重要,因為這些結(jié)構(gòu)依賴哈希值進行快速查找和存儲,為了減少哈希沖突

equals和hashCode的關(guān)系

1.基本規(guī)則:

  • 如果兩個對象根據(jù) equals 方法被認為是相等的,那么它們的 hashCode 值必須相等。
  • 如果兩個對象的 hashCode 值相等,它們不一定通過 equals 方法相等。

2.原因:

  • 哈希表數(shù)據(jù)結(jié)構(gòu)(如 HashMap、HashSet)使用對象的哈希碼(hashCode)來快速查找對象。
  • 當(dāng)你向 HashSet 中添加一個對象時,集合會先調(diào)用該對象的 hashCode 方法來找到該對象應(yīng)放置的“桶”(bucket)。
  • 如果在桶中找到了對象的哈希碼相同的其他對象,集合會再調(diào)用 equals 方法來判斷這些對象是否真正相等。

equals 方法

用于比較兩個對象的內(nèi)容是否相同。

默認情況下(如果沒有重寫),Object類中的equals方法是比較兩個對象的內(nèi)存地址(即引用),只有當(dāng)兩個引用指向同一個對象時才返回true。

哈希表的工作原理

  • 哈希碼 (hashCode) 用于快速定位對象: 哈希表使用哈希碼來將對象分配到不同的“桶”中,從而加速查找過程。哈希碼相同的對象會被放置在同一個桶中。
  • 相等 (equals) 方法 用于在桶中比較對象: 當(dāng)兩個對象的哈希碼相同(即它們位于同一個桶中),哈希表會使用 equals 方法來逐一比較這些對象,以判斷它們是否真的是相等的。

為什么 equals 和 hashCode 必須保持一致性?

假設(shè)兩個對象相等(x.equals(y) 返回 true),但它們的哈希碼不同(x.hashCode() != y.hashCode()):

  • 在這種情況下,如果將其中一個對象添加到 HashSet 中,然后查找另一個對象,哈希表會去不同的桶中查找,這樣可能找不到它。
  • 這違背了 HashSet 等集合的合同,即它們不允許重復(fù)對象(根據(jù) equals 方法判斷相等)。

如果兩個對象的哈希碼相同(x.hashCode() == y.hashCode()),但它們不相等(x.equals(y) 返回 false):

  • 這是可以的,因為哈希表會使用 equals 方法來判斷真正的相等性。
  • 唯一的影響是性能上的下降,因為桶中的對象數(shù)量增加了。

HashSet

HashSet 的基本工作原理

HashSet 是基于 哈希表 實現(xiàn)的集合,它用于存儲沒有重復(fù)值的對象。

它的效率很高,通常 addremovecontains 操作都可以在常量時間(O(1))內(nèi)完成。然而,這種高效率依賴于正確實現(xiàn) hashCodeequals 方法。

工作步驟:

  1. 添加元素到 HashSet 中: 當(dāng)你調(diào)用 HashSetadd 方法時,HashSet 會先調(diào)用該對象的 hashCode 方法計算出該對象的哈希碼。
  2. 查找存儲桶(bucket): HashSet 使用哈希碼來決定將該對象存儲在哪個 桶(bucket) 中。每個桶可以包含多個對象(這是處理哈希沖突的方式)。桶是 HashSet 中用于存儲對象的數(shù)組中的某個位置。
  3. 檢查對象的相等性: 如果哈希表中已經(jīng)有其他對象在相同的桶中,HashSet 會通過調(diào)用 equals 方法逐個比較這些對象,看看新對象是否已經(jīng)存在。如果 equals 返回 true,則 HashSet 不會再插入這個對象,因為集合中不能有重復(fù)的對象。
  4. 添加到集合: 如果 hashCodeequals 都確認新對象與集合中的任何對象都不相等,HashSet 就會把這個新對象放入集合中。

hashCode 和 equals 如何協(xié)作

1. hashCode 用于快速定位

  • 當(dāng)插入或查找元素時,HashSet 首先根據(jù)對象的 hashCode 值找到相應(yīng)的桶(bucket)。
  • 哈希碼的作用是將對象分散到不同的桶中,以提高查詢效率。

2. equals 用于精確比較

  • 因為不同對象可能有相同的 hashCode 值(稱為哈希沖突),所以 HashSet 在找到對應(yīng)的桶后,還需要進一步用 equals 方法檢查桶中是否有真正相等的對象。
  • 如果 equals 返回 true,表示這個對象已經(jīng)存在,不再添加。

哈希沖突

哈希沖突(Hash Collision)是在使用哈希表或類似的數(shù)據(jù)結(jié)構(gòu)時,兩個或多個不同的對象生成了相同的哈希碼(hashCode),導(dǎo)致它們被存儲在哈希表的同一個位置(即同一個桶,bucket)。雖然哈希碼相同,但這些對象在邏輯上是不相等的(equals 返回 false)。

為什么會發(fā)生哈希沖突?

哈希碼的范圍是有限的(通常是32位整數(shù)),但可能存儲的對象組合是無限的。

因此,不同的對象有可能生成相同的哈希值,這是哈希沖突發(fā)生的根本原因。

如何處理哈希沖突?

現(xiàn)代哈希表通過多種方式處理哈希沖突,以下是常見的兩種方法:

鏈地址法(Separate Chaining):

  • 當(dāng)多個對象具有相同的哈希值時,它們會存儲在同一個“桶”中,而每個桶內(nèi)部可以通過鏈表、樹等數(shù)據(jù)結(jié)構(gòu)來存放多個對象。
  • 當(dāng)需要查找對象時,先通過哈希值找到對應(yīng)的桶,然后再在桶內(nèi)通過逐個比較 equals 來找到目標對象。

開放地址法(Open Addressing):

  • 這種方法不使用鏈表,而是當(dāng)哈希沖突發(fā)生時,直接尋找哈希表中下一個可用的位置(通過某種探查策略,如線性探查、二次探查等),將對象存儲到其他空閑位置。

哈希沖突的影響

  • 哈希沖突會導(dǎo)致哈希表的性能下降,因為需要處理沖突的額外操作,如遍歷鏈表或進行線性探查。
  • 當(dāng)沖突過多時,哈希表的操作效率會從理想的 O(1) 降到 O(n),特別是在極端情況下(例如所有對象都被放入同一個桶中)。

如何降低哈希沖突的發(fā)生

1.使用良好的哈希碼算法:

  • 避免簡單的哈希計算,如直接返回某個字段的值。
  • Java 中常用的做法是結(jié)合對象的多個字段進行哈希碼的計算,并使用質(zhì)數(shù)乘數(shù)(例如 31)來減少沖突。

2.均勻分布哈希碼:

  • 確保 hashCode 方法生成的哈希值在可能的范圍內(nèi)盡量均勻分布。
  • 不同的對象應(yīng)該有不同的哈希碼,即使它們的某些屬性相同。

哈希沖突是不可避免的,因為哈希碼的范圍有限,而對象的可能組合是無限的。因此,即使是使用良好的哈希算法,也難以避免沖突。

總結(jié)

在 Java 中,`equals` 和 `hashCode` 方法密切相關(guān),必須保持一致性:如果兩個對象通過 `equals` 方法相等,它們的 `hashCode` 也必須相同。

這對于基于哈希的數(shù)據(jù)結(jié)構(gòu)(如 `HashMap`、`HashSet`)至關(guān)重要,因為這些結(jié)構(gòu)依賴哈希值進行快速查找和存儲。

為了減少哈希沖突,`hashCode` 的計算通常結(jié)合多個字段,并使用質(zhì)數(shù)(如 31)進行乘法,以保證哈希值的均勻分布和較低的沖突率。設(shè)計良好的 `equals` 和 `hashCode` 方法可以確保對象比較的準確性與哈希結(jié)構(gòu)的高效性。

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

相關(guān)文章

  • JAVA垃圾收集器與內(nèi)存分配策略詳解

    JAVA垃圾收集器與內(nèi)存分配策略詳解

    這篇文章介紹了JAVA垃圾收集器與內(nèi)存分配策略,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2015-07-07
  • Spring框架實現(xiàn)文件上傳功能

    Spring框架實現(xiàn)文件上傳功能

    這篇文章主要為大家詳細介紹了Spring框架實現(xiàn)文件上傳功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • Java?Servlet響應(yīng)httpServletResponse過程詳解

    Java?Servlet響應(yīng)httpServletResponse過程詳解

    HttpServletResponse是處理http響應(yīng)的對象,調(diào)用該對象的方法,設(shè)置到對象屬性的內(nèi)容,tomcat最終會組織為http響應(yīng)報文
    2022-02-02
  • Spring中allowedOriginPatterns和allowedOrigins方法有何不同詳解

    Spring中allowedOriginPatterns和allowedOrigins方法有何不同詳解

    這篇文章主要給大家介紹了關(guān)于Spring中allowedOriginPatterns和allowedOrigins方法有何不同,allowedOriginPatterns和allowedOrigins都是用來設(shè)置允許跨域請求的來源,需要的朋友可以參考下
    2023-10-10
  • SpringBoot如何注冊Servlet、Filter、Listener的幾種方式

    SpringBoot如何注冊Servlet、Filter、Listener的幾種方式

    在Servlet 3.0之前都是使用web.xml文件進行配置,這篇文章主要介紹了SpringBoot如何注冊Servlet、Filter、Listener的幾種方式,在Servlet 3.0之前都是使用web.xml文件進行配置,
    2018-10-10
  • springboot打成jar后無法讀取根路徑和文件的解決

    springboot打成jar后無法讀取根路徑和文件的解決

    這篇文章主要介紹了springboot打成jar后無法讀取根路徑和文件的解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • 盤點Java中延時任務(wù)的多種實現(xiàn)方式

    盤點Java中延時任務(wù)的多種實現(xiàn)方式

    當(dāng)需要一個定時發(fā)布系統(tǒng)通告的功能,如何實現(xiàn)??當(dāng)支付超時,訂單自動取消,如何實現(xiàn)?其實這些問題本質(zhì)都是延時任務(wù)的實現(xiàn),本文為大家盤點了多種常見的延時任務(wù)實現(xiàn)方法,希望對大家有所幫助
    2022-12-12
  • JDBC獲取數(shù)據(jù)庫連接的5種方式實例

    JDBC獲取數(shù)據(jù)庫連接的5種方式實例

    JDBC是一種用于執(zhí)行SQL語句的JavaAPI,為多種關(guān)系數(shù)據(jù)庫提供統(tǒng)一訪問,它由一組用Java語言編寫的類和接口組成,提供了諸如查詢和更新數(shù)據(jù)庫中數(shù)據(jù)的方法,這篇文章主要給大家介紹了關(guān)于JDBC獲取數(shù)據(jù)庫連接的5種方式,需要的朋友可以參考下
    2022-06-06
  • 詳細解析Java中抽象類和接口的區(qū)別

    詳細解析Java中抽象類和接口的區(qū)別

    這篇文章主要介紹了Java中抽象類和接口的區(qū)別詳解,需要的朋友可以參考下
    2014-10-10
  • Java的main方法使用及說明

    Java的main方法使用及說明

    這篇文章主要介紹了Java的main方法使用及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08

最新評論