为什么 Netbeans 会以这种方式生成 hashCode()?

2022-09-03 15:32:42

我已经用 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 generate hashcode”之类的东西,发现没有发现任何相关的内容。在座的有没有人熟悉这一代战略是什么,以及 Netbeans 为什么使用它?

编辑:
感谢您到目前为止的答案!特别是由于链接的SO问题的这个答案,我现在更全面地理解了使用素数设计hashCode方法背后的逻辑。然而,到目前为止还没有人真正解决我的问题的另一个方面是Netbeans如何以及为什么选择它为其生成的方法所做的素数。字段和其他乘数(在我的例子中)似乎根据类的各种因素而有所不同。hash89

例如,如果我向类中添加第二个,hashCode() 变为String

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 选择这些特定的素数,而不是任何其他素数呢?


答案 1

这是一项优化,旨在更好地分配哈希值。Eclipse也做了类似的工作。看看为什么在hashCode中使用素数?为什么字符串中的Java的hashCode()使用31作为乘数?

这绝不是必需的。甚至足以满足相等/哈希码协定。唯一的原因是,基于哈希的数据结构在良好的分布式哈希值下性能更好。return 0;

有些人会称之为过早优化。我想这没关系,因为它是a)免费(生成)和b)广泛认可(几乎每个IDE都这样做)。


答案 2

IBM 有一篇关于如何编写自己的方法的文章。他们正在做的事情很好,尽管31往往是一个更好的素数,因为乘法可以更好地优化。equals()hashCode()

也看看 String.hashCode() 是如何工作的。正是如此,但具有不同的素数和齐次类型。