重寫 hashcode真有那么簡單嘛?

萬萬沒想到一個 hashcode() 方法,既然會引出一堆的知識盲區,簡直了 。
起因:

老八股:為什么重寫Equals方法要重寫HashCode方法 。
大聲告訴我為什么 , 閉著眼睛先把答案背出來,啥?這都忘了?沒事,也不是啥大事 。這兩句話再Object類的 hashcode 中的注釋上就有 , 但是一般八股文不會告訴你是出自這里的 。凝聚成兩句話就是:
1 如果兩個對象通過equals()方法比較相等,那么這兩個對象的hashCode一定相同 。
2 如果兩個對象hashCode相同,不能證明兩個對象是同一個對象(不一定相等),只能證明兩個對象在散列結構中存儲在同一個地址(不同對象hashCode相同的情況稱為hash沖突) 。
  • 標準嘛,很標準,但是還不夠 , 一般人到這里已經結束了,但是我還想和面試官在掰扯一下:從Object類中 hashcode 的注釋上就寫著很明白了,具體如下
/*** Returns a hash code value for the object. This method is* supported for the benefit of hash tables such as those provided by* {@link java.util.HashMap}.* <p>* The general contract of {@code hashCode} is:* <ul>* <li>Whenever it is invoked on the same object more than once during*an execution of a Java application, the {@code hashCode} method*must consistently return the same integer, provided no information*used in {@code equals} comparisons on the object is modified.*This integer need not remain consistent from one execution of an*application to another execution of the same application.* <li>If two objects are equal according to the {@code equals(Object)}*method, then calling the {@code hashCode} method on each of*the two objects must produce the same integer result.* <li>It is <em>not</em> required that if two objects are unequal*according to the {@link java.lang.Object#equals(java.lang.Object)}*method, then calling the {@code hashCode} method on each of the*two objects must produce distinct integer results.However, the*programmer should be aware that producing distinct integer results*for unequal objects may improve the performance of hash tables.* </ul>* <p>* As much as is reasonably practical, the hashCode method defined by* class {@code Object} does return distinct integers for distinct* objects. (This is typically implemented by converting the internal* address of the object into an integer, but this implementation* technique is not required by the* Java&trade; programming language.)** @returna hash code value for this object.* @seejava.lang.Object#equals(java.lang.Object)* @seejava.lang.System#identityHashCode*/public native int hashCode();
  • 看著很長 , 其實不然,給你們翻譯一下第一句話---什么叫中式翻譯,如下
Returns a hash code value for the object. This method is supported for the benefit of hash tables such as those provided by
返回 一個 hash code 值 為 這個 對象 。這個 方法 是 支持 的 這個 好處 體現為 hash 表 比如 這些 提供的 {@link java.util.HashMap}.
權威解釋什么亂七八糟的,還是來看看比較權威的 。
  • Effective Java 第三版 中 描述為什么重寫equals 方法后必須重寫hashCode 方法
每個覆蓋了equals方法的類中,必須覆蓋hashCode 。如果不這么做,就違背了hashCode的通用約定,也就是上面注釋中所說的 。進而導致該類無法結合所以與散列的集合一起正常運作,這里指的是HashMap、HashSet、HashTable、ConcurrentHashMap 。
提煉:如果重寫equals不重寫hashCode它與散列集合無法正常工作 。
總結:恍然大悟,原來是這樣,那我這個對象,不存在這些散列集合中不就不用遵守這個規則了嘛 。哈哈,大聰明 , 理論上確實是這樣 。但是這篇文章我還想再寫長一些,多占用一些面試時間 , 畢竟我還有主動權機會 。
hashcode()”偽源碼“
  • 首先聲明一點:Object 提供的 hashCode()方法返回值是不會重復的(也就是說每個對象返回的值都不一樣) 。
有人說,扯淡嘛,我看了Object類中的hashcode()方法 , 里面什么也沒有啊 , 只有方法 , 沒看到實現 , 哪里來的返回值呢 。
public native int hashCode();關鍵字 native首先看到看關鍵字 native , 知識盲區來了 , 很多人不知道 這是啥東西 , 當然,說起這個,就要從盤古開天辟地開始講了,我們這一節也不著重講這個,篇幅有限,感興趣的去問問度娘吧 。
  • 先看概念:
native 用來修飾方法,用 native 聲明的方法表示告知 JVM 調用,該方法在外部定義,我們可以用任何語言去實現它 。簡單地講,一個native Method就是一個 Java 調用非 Java 代碼的接口 。

推薦閱讀