我们已经了解了怎么重写 equals 方法了,接下来就一起了解如何重写 hashcode 方法,我们知道 hashcode 方法返回的是一个 int 类型的方法,那好办呀,像下面这样重写就行了
@Override public int hashCode() { return 1; }这样写对吗?对错先不管,我们先来看一下 hashcode 在 Object 中的规定:
1、当在一个应用程序执行过程中,如果在 equals 方法比较中没有修改任何信息,在一个对象上重复调用 hashCode 方法时,它必须始终返回相同的值。从一个应用程序到另一个应用程序的每一次执行返回的值可以是不一致的。
2、如果两个对象根据 equals(Object) 方法比较是相等的,那么在两个对象上调用 hashCode 就必须产生的结果是相同的整数。
3、如果两个对象根据 equals(Object) 方法比较并不相等,则不要求在每个对象上调用 hashCode 都必须产生不同的结果。
照 hashcode 规定来看,这样写似乎也没什么问题,但是你应该知道哈希表,如果这样写的话,对于HashMap 和 HashSet 等散列表来说,直接把它们废掉了,在哈列表中,元素映射到数组的哪个位置靠 hashcode 决定,而我们的 hashcode 始终返回 1 ,这样的话,每个元素都会映射到相同的位置,散列表也会退化成链表。
结合 hashcode 的规范和散列表来看,要重写出一个高质量的 hashcode 方法,就需要尽可能保证每个元素产生不同的 hashcode 值,在 JDK 中,每个引用类型都重写了 hashcode 函数,我们看看 String 类中的 hashcode 是如何重写的:
public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }这个 hashcode 方法写的还是非常好的,我个人比较喜欢用官方的东西,我觉得他们考虑的肯定比我们多很多,所以我们 Article 类的 hashcode 方法就可以这样写
/** * 重写 hashcode方法,根据url返回hash值 * @return */ @Override public int hashCode() { return url.hashCode(); }我们直接调用 String 对象的 hashcode 方法。到此我们的 equals 方法和 hashcode 方法都重写完了,最后以 effective-java 里面的一段总结结尾吧。
1、当重写 equals 方法时,同时也要重写 hashCode 方法
2、不要让 equals 方法试图太聪明。
3、在 equal 时方法声明中,不要将参数 Object 替换成其他类型。
文章不足之处,望大家多多指点,共同学习,共同进步
最后打个小广告,欢迎扫码关注微信公众号:「平头哥的技术博文」,一起进步吧。