重写 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 代码的接口 。

推荐阅读