美文网首页Java 杂谈
重写hashCode 方法的注意事项

重写hashCode 方法的注意事项

作者: joyhj | 来源:发表于2018-08-22 12:28 被阅读1次

java.lang.Object 中的hashCode方法如下

public native int hashCode();

上面使用了native关键字,说明这是一个本地方法。

关于native关键字的介绍,请查看这里

什么时候需要重写hashCode方法

在每个类中,在重写 equals 方法的时侯,一定要重写 hashcode 方法。如果不这样做,你的类违反了hashCode的通用约定,这会阻止它在HashMap和HashSet这样的集合中正常工作。

重写hashCode方法的约定

重写hashCode方法的注意事项写在了方法说明中,可以点击这里查看。

翻译过来的要点如下

当在一个应用程序执行过程中,如果在equals方法比较中没有修改任何信息,在一个对象上重复调用hashCode方法时,它必须始终返回相同的值。从一个应用程序到另一个应用程序的每一次执行返回的值可以是不一致的。
如果两个对象根据equals(Object)方法比较是相等的,那么在两个对象上调用hashCode就必须产生的结果是相同的整数。
如果两个对象根据equals(Object)方法比较并不相等,则不要求在每个对象上调用hashCode都必须产生不同的结果。 但是,程序员应该意识到,为不相等的对象生成不同的结果可能会提高散列表(hash tables)的性能。

重写hashCode的例子

一个重写phoneNum类 hashCode的例子,前半部分phoneNum类的代码参考这儿

// Typical hashCode method

@Override public int hashCode() {

    int result = Short.hashCode(areaCode);

    result = 31 * result + Short.hashCode(prefix);

    result = 31 * result + Short.hashCode(lineNum);

    return result;

}

这个方法返回一个简单的确定性计算的结果,它的唯一的输入是PhoneNumber实例中的三个重要的属性,所以显然相等的PhoneNumber实例具有相同的哈希码.
实际上,这个方法是PhoneNumber的一个非常好的hashCode实现,与Java平台类库中的实现一样。 它很简单,速度相当快,并且合理地将不相同的电话号码分散到不同的哈希桶中。

虽然在这个项目的方法产生相当好的哈希函数,但并不是最先进的。 它们的质量与Java平台类库的值类型中找到的哈希函数相当,对于大多数用途来说都是足够的。 如果真的需要哈希函数而不太可能产生碰撞,请参阅Guava框架的com.google.common.hash.Hashing.java

那有没有比较省力不容易出错的方法?答案是有的,那就是使用google 的AutoValue开源框架或者IDE自动生成功能。使用AutoValue框架,只需要在类上添加一个注解,框架就会自动帮你生成equals方法。

参考文章:

Effective Java 第三版——11. 重写equals方法时同时也要重写hashcode方法

相关文章

网友评论

    本文标题:重写hashCode 方法的注意事项

    本文链接:https://www.haomeiwen.com/subject/hwpdiftx.html