日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

彻底搞懂为什么重写equals还要重写hashcode?

發布時間:2024/3/12 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 彻底搞懂为什么重写equals还要重写hashcode? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

引言

原文鏈接:深入理解equals和hashCode?由于hashCode與HashMap有一定關系,推薦大家看一下我的這篇文章?HashMap源碼大剖析?

?

本文介紹java.lang.Object類中的兩個方法:equals和hashCode。這兩個方法大家應該都知道,但是這兩個方法的作用是什么、為什么重寫equals還要重寫hashCode、它們之間有什么關系和約定等,或許有些小伙伴還不是很清楚,知其然知其所以然,今天就來帶大家了解一下。

百度搜索"為什么重寫equals一定要重寫hashcode",第二條結果就是我寫的文章。這是我很久之前寫的,其中的內容表述得不太清楚,或多或少難以讓人信服,于是我決定再寫一篇。

1、hashCode

在閱讀下面的內容之前,大家可能需要先了解一下什么是哈希表、哈希函數,這是數據結構相關的知識。

hashCode即散列碼。散列碼是用一個int值來代表對象,它是通過將該對象的某些信息進行轉換而生成的。

Object類中默認的hashCode方法如下。

public?native?int?hashCode();

這是一個本地方法,不同的虛擬機有不同的實現(具體實現自己看虛擬機源碼哈)。Object默認的hashCode是根據對象的內存地址轉化而來的,它是唯一的。

我們可以在自己的類中覆蓋hashCode方法,但我們可以使用System.identityHashCode(Object x)方法返回默認的hashcode,無論對象是否覆蓋默認的hashcode。

hashCode方法主要是為了給諸如HashMap這樣的哈希表使用

設計hashcode最重要的因素是:對同一個對象調用hachCode()應該產生同樣的值(前提是對象的信息沒有被改變)。

設計一個hashCode,它必須快,而且具有意義(使用有意義的字段來生成hashcode)。hashCode不需要唯一(默認的hashCode唯一),因此更應該關注它的速度,而不是唯一性

由于在生成桶(桶指哈希桶,或哈希表的槽位)的下標前,hashcode還要做進一步處理,所以生成的hashCode范圍不是很重要,是int就行。

好的hashCode()應該產生分布均勻的散列碼。

哈希桶的大小最好是2的n次方。

  • 對現代處理器來說,除數和求余是最慢的操作,而使用2的n次方,可以用位運算代替求余(%開銷較大)。

  • 舉個例子,假設哈希桶大小為16(HashMap初始大小),假設hashCode為20,那么使用%求余會得到下標4;但這可以用hashCode&(length-1)代替,即20&(16-1),結果也是4。

2、equals

hashCode并不需要唯一性,但equals必須嚴格地判斷兩個對象是否相同。

正確的equals方法有如下特性:

  • 自反性:x.equals(x)一定返回true

  • 對稱性:如果x.equals(y)為true,那么y.equals(x)也為true

  • 傳遞性:如果x.equals(y)為true、y.equals(z)為true,那么x.equals(z)也為true

  • 一致性:如果x和y中用于等價比較的信息沒有改變,那么x.equals(y)無論調用多少次,結果都一致

  • 任何不是null的x,x.equals(null)一定返回false

3、equals與hashCode的相關規定

之所以有規定,是為了使諸如HashMap這樣的哈希表正常使用。具體規定如下:

  • equals相等,hashcode一定相等。

  • equals不等,hashcode不一定不等。

  • hashcode不等,equals一定不等。

  • hashcode相等,equals不一定相等。

  • 因此,如果我們重寫了equals,那么必須重寫hashCode,使其滿足這些規定。當然,如果我們不把自定義對象當成HashMap的鍵來使用,那么自定義對象不重寫equals和hashCode也是可以的。

    下面來詳細解釋一下,為什么這些規定能讓HashMap正常工作。

    3.1、equals相等,hashCode一定相等

    因為HashMap是用equals判斷鍵是否相等的,用反證法,如果兩個鍵 equals相等,而hashcode不等的話,那么就無法保證通過hashcode計算的下標值相等,下標值不等也就意味著相等的兩個鍵卻 到了不同的值,這肯定是不對的。

    3.2、equals不等,hashcode不一定不等

    equals不等,一般hashcode也不相等,這是為了盡量減少哈希沖突。但為啥會出現相等的情況呢,因為hashcode是int類型,是有范圍的,當數據量很大的情況下,難免會發生沖突,此時HashMap通過拉鏈法解決沖突。

    當從map中獲取equals不等的兩個鍵時,由于它們的hashcode相同,所以計算到的下標值也相同,當定位到同一個桶位時,會在單鏈表上順序查找,查找到的依據就是要查找的鍵與單鏈表上的鍵equals相等。

    3.3、hashcode不等,equals一定不等

    這個相當于規定1的逆反命題。

    3.4、hashcode相等,equals不一定相等

    這個相當于規定2的逆反命題。如果兩個鍵hashcode相等,那么計算到的下標值是相同的,這時候兩個鍵可能是相等的(該桶位有一個元素),也可能是不等的(該桶位有兩個元素)。

    總結

    以上是生活随笔為你收集整理的彻底搞懂为什么重写equals还要重写hashcode?的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。