[英]Why does Netbeans generate hashCode() the way that it does?
我已经用Netbeans开发了一段时间的Java,并且有些事情我只是依赖于工作而没有真正质疑如何。 其中包括自动生成的hashCode()和equals()方法。
equals方法很容易遵循,但我发现hashCode方法有些神秘。 我不明白为什么它选择乘数并应用它所做的操作。
import java.util.Arrays;
import java.util.Objects;
public class Foo {
int id;
String bar;
byte[] things;
@Override
public int hashCode() {
int hash = 7;
hash = 89 * hash + this.id;
hash = 89 * hash + Objects.hashCode(this.bar);
hash = 89 * hash + Arrays.hashCode(this.things);
return hash;
}
}
搜索文档,这个网站和谷歌搜索“netbeans生成哈希码”之类的内容,似乎没有任何相关内容。 有谁在这里熟悉这一代策略是什么以及为什么Netbeans使用它?
编辑:
谢谢你到目前为止的答案! 特别是由于对链接SO问题的这个答案 ,我理解现在更充分地使用素数来设计hashCode方法的逻辑。 然而,到目前为止我没有真正解决的问题的另一个方面是Netbeans如何以及为什么选择它为其生成的方法所做的素数。 hash
字段和另一个乘数(在我的示例中为89
)似乎根据类的各种因素而不同。
例如,如果我向该类添加第二个String
,则hashCode()变为
public int hashCode() {
int hash = 7;
hash = 13 * hash + this.id;
hash = 13 * hash + Objects.hashCode(this.bar);
hash = 13 * hash + Objects.hashCode(this.baz);
hash = 13 * hash + Arrays.hashCode(this.things);
return hash;
}
那么,为什么Netbeans会选择这些特定的素数而不是其他素数?
这是一种旨在更好地分配哈希值的优化。 Eclipse也是这样做的。 看看为什么在hashCode中使用素数? 为什么String中的Java hashCode()使用31作为乘数? 。
这绝不是必需的。 甚至return 0;
足以满足equals / hashcode合约。 唯一的原因是基于散列的数据结构在良好的分布式散列值下表现更好。
有人会称之为过早优化。 我想这是可以的,因为它a)免费(生成)和b)广泛认可(几乎每个IDE都这样做)。
IBM有一篇关于如何编写自己的equals()
和hashCode()
方法的文章。 他们正在做的很好,虽然31往往是一个更好的素数,因为乘法可以更好地优化。
另请String.hashCode()
工作原理 。 正是如此,但具有不同的素数和同类型。
来自Joshua Bloch的第9项, Effective Java 2nd ed。 ,要记住的重要一点是在覆盖equals()时始终覆盖hashCode()以确保相等的对象具有相同的哈希码 - 否则您可能很容易违反此契约。 虽然他说最先进的哈希函数是博士研究的主题,但他为一个好的通用hashCode提供的配方在你的情况下可能会产生:
@Override
public int hashCode() {
int result = 17;
result = 31 * result + id;
result = 31 * result + bar.hashCode();
result = 31 * result + Arrays.hashCode(things);
return result ;
}
正如@zapl和David Ehrmann所提到的,编译器可以很容易地将31的乘法优化为位移和减1运算,因此如果这很重要,可能会更快一些。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.