自定義類如何重寫hashcode()方法


要重寫自己的hashCode方法並沒有什么絕對正確的答案,但是我們的目標是:不相等的對象盡可能有不同的hashCode,而且必須滿足的一個通用約定是:相等的對象應該具有相同的hashCode。下面介紹一種hashCode的實現方式,這種實現方式對一般的程序來說足夠了,至於如何實現更完美的hashCode方法就留給數學家或者理論家去討論吧。

第一步:定義一個初始值,一般來說取17

int result = 17;

第二步:分別解析自定義類中與equals方法相關的字段(假如hashCode中考慮的字段在equals方法中沒有考慮,則兩個equals的對象就很可能具有不同的hashCode)

    情況一:字段a類型為boolean 則[hashCode] = a ? 1 : 0;

    情況二:字段b類型為byte/short/int/char, 則[hashCode] = (int)b;

    情況三:字段c類型為long, 則[hashCode] = (int) (c ^ c>>>32);

    情況四:字段d類型為float, 則[hashCode] = d.hashCode()(內部調用的是Float.hashCode(d), 而該靜態方法內部調用的另一個靜態方法是Float.floatToIntBits(d))

    情況五:字段e類型為double, 則[hashCode] = e.hashCode()(內部調用的是Double.hashCode(e), 而該靜態方法內部調用的另一個靜態方法是Double.doubleToLongBits(e),得到一個long類型的值之后,跟情況三進行類似的操作,得到一個int類型的值)

    情況六:引用類型,若為null則hashCode為0,否則遞歸調用該引用類型的hashCode方法。

    情況七:數組類型。(要獲取數組類型的hashCode,可采用如下方法:s[0]*31 ^ (n-1) + s[1] * 31 ^ (n-2) + ..... + s[n-1], 該方法正是String類的hashCode實現所采用的算法)

第三步:對於涉及到的各個字段,采用第二步中的方式,將其依次應用於下式:

result = result * 31 + [hashCode];

補充說明一點:如果初始值result不取17而取0的話,則對於hashCode為0的字段來說就沒有區分度了,這樣更容易產生沖突。比如兩個自定義類中,一個類比另一個類多出來一個或者幾個字段,其余字段全部一樣,分別new出來2個對象,這2個對象共有的字段的值全是一樣的,而對於多來的那些字段的值正好都是0,並且在計算hashCode時這些多出來的字段又是最先計算的,這樣的話,則這兩個對象的hashCode就會產生沖突。還是那句話,hashCode方法的實現沒有最好,只有更好。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM