重写 hashcode真有那么简单嘛?( 四 )

Person key = new Person("1","张三");Person sameKey = new Person("1","张三");Person unSameKey = new Person("2","张三");

其中 key 和 sameKey 的 hashcode()一定要相同 , 因为我们的业务员就是认为他们应该是相同的 。但是同时 unSame 和 key 的 hashcode() 一定不能相同 。
  • 这个时候 , 使用Object的 hashcode() 很显然就是不行了 , 应为它返回每个对象的 hashcode() 都是不相同的 。
  • 当然了 , 所有 hashcode() 都返回 0  , 这也不是不行 , 只是违背了这句话:如果两个对象hashCode相同 , 不能证明两个对象是同一个对象(不一定相等) 。
来吧 , 开始发散思维 。
方法一:
  • 使用String 的hashcode() , 你对象里面的属性不是String 类型嘛 , String 里面已经重写了 hashcod() 方法那我直接用现成的就好了 。
@Overridepublic int hashCode() {returnid.hashCode() + name.hashCode();}
但是我们还是要从各个角度出发去想一下的 , 比如判空 , 是否会值溢出之类的 , 这里我们也参考String 的 hashcode() 套娃一个 。优化后:
@Overridepublic int hashCode() {//初始值 , 别问为什么是 17, 因为我写 18 你也会这样问的int result = 17;// 31 作为基数 , 不知道啊 , String 里面 的 hashcode() 就是写的 31result = 31 * result + (id == null ? 0 : id.hashCode());result = 31 * result + (name == null ? 0 : name.hashCode());return result;}方法二:
  • 调用JDK提供好的Objects里面的hashcode()
@Overridepublic int hashCode() {return Objects.hash(id,name);}看了这两个方法 , 没错 , 这都是站在巨人的肩膀上 。其实要是自己动手实现 , 那难度就直线上升了 , 至少算法这一块要啃一下 。
hashcode() 方重写规则
写hashcode()要遵循以下原则:
equals不相等时并不强制要求哈希值相等 , 但是一个优秀的哈希算法应尽可能让元素均匀分布 , 降低冲突发生的概率 , 即在equals不相等时尽量让哈希值也不相等 , 这样&&或||短路操作一旦生效 , 会极大提高程序的效率 。
重写equals都是根据业务需求去进行重写的 , 想想为什么String是这么判断两个字符串对象相等的 。如果抛开业务需求谈这个 , 就是耍流氓 。但是大多数情况下 , 都是不用重写 equals() 和 hashcode() 的 , 就是因为有了特殊的业务逻辑 , 所以我们才需要重写里面的逻辑 。
知识盲区
不想写了 ,  今天就先结束吧 , 呼应一下开头 , 看看都涉及到哪些知识点 , 下次再遇到这样的八股文 , 一开口就能聊几个小时 。
1、hashcode() 方法是 native 关键字修饰的 , 你有了解过嘛、Java方法和本地方法有什么不同、为什么要注册本地方法呢?
2、Object类中并没有hashcode() 方法源码 , 真正的源码应该去哪里看
3、jdk 源码目录 , 你真正打开过jdk源码嘛
4、 hashcode() 源码上有 @seejava.lang.System#identityHashCode 。那你知道 这两个方法有什么区别嘛
5、hashcode() 方法一定要重写 , 强调的是和hash表相关 , 那你知道源码中都是这么体现的嘛
6、hashcode() 手写实现 , 需要有什么功底呢?
7、调用了 String 的 hashcode() 去实现 , 那你知道 String#hashcode() 中为什么要用常数 31 嘛

经验总结扩展阅读