使用Objects.hash()或自己的hashCode()实现?

Her*_*erb 50 java hash

我最近发现了这种Objects.hash()方法.

我的第一个想法是,这会整理你的hashCode()实施.请参阅以下示例:

@Override
//traditional
public int hashCode() {
    int hash = 5;
    hash = 67 * hash + (int)(this.id ^ (this.id >>> 32));
    hash = 67 * hash + (int)(this.timestamp ^ (this.timestamp >>> 32));
    hash = 67 * hash + Objects.hashCode(this.severity);
    hash = 67 * hash + Objects.hashCode(this.thread);
    hash = 67 * hash + Objects.hashCode(this.classPath);
    hash = 67 * hash + Objects.hashCode(this.message);
    return hash;
}

@Override
//lazy
public int hashCode() {
    return Objects.hash(id, timestamp, severity, thread, classPath, message);
}
Run Code Online (Sandbox Code Playgroud)

虽然我不得不说这看起来好得令人难以置信.我也从未见过这种用法.

Objects.hash()与实现自己的哈希代码相比,使用是否有任何缺点?我什么时候会选择这些方法?

更新

虽然此主题已标记为已解决,但您可以随时发布提供新信息和疑虑的答案.

And*_*ner 55

注意参数Objects.hashObject....这有两个主要后果:

  • 哈希码计算中使用的原始值必须加框,例如this.id从转换longLong.
  • 一个Object[]必须创建要调用的方法.

如果hashCode频繁调用,则创建这些"不必要"对象的成本可能会增加.

  • 与所有性能问题一样,您应该在照顾之前向自己证明您在乎. (17认同)
  • @CandiedOrange是的; 另一方面,不要编写您*可能*必须关心的代码.我的意思是,你可以实现`hashCode`和`return 0;`如果你不打算关心性能,除非你已经证明了.由于您只需要编写一次,并且您的IDE可能会为您生成代码,因此您也可以选择详细但高性能的版本.但我不会急于在现有代码中将任何一种形式更改为另一种形式. (4认同)

nag*_*547 25

以下是Objects.hash的实现- 它在内部调用Arrays.hashCode.

public static int hash(Object... values) {
    return Arrays.hashCode(values);
}
Run Code Online (Sandbox Code Playgroud)

这是Arrays.hashCode方法的实现

public static int hashCode(Object a[]) {
    if (a == null)
        return 0;

    int result = 1;

    for (Object element : a)
        result = 31 * result + (element == null ? 0 : element.hashCode());

    return result;
}
Run Code Online (Sandbox Code Playgroud)

所以我同意@Andy如果经常调用hashCode,那么创建这些"不必要"对象的成本可能会增加.如果你自己实现它会更快.


Tez*_*zra 10

我想尝试为两者做出强有力的论据.

打开免责声明

对于这个答案,Objects.hash(),Objects.hashCode(),和任何功能由执行这个角色是可以互换的任何库提供.首先,我想争论,使用Objects.hash()或者根本不使用静态对象功能.支持或反对此方法的任何参数都需要对编译后的代码进行假设,这些假设不能保证为真.(例如,编译器优化器可能会将函数调用转换为内联调用,从而绕过额外的调用堆栈和对象分配.就像没有任何用处的循环没有进入编译版本一样(除非你关闭优化器).你也不能保证未来的Java版本不会包含像C#那样的JVM版本.这个方法的版本也是如此.(出于安全考虑,我相信))所以你可以使用这个函数做出唯一安全的论证,将这个函数的正确哈希的细节留给试图实现你自己的天真版本通常更安全.

对于Objects.hash

  • 保证是一个很好的哈希.
  • 需要5秒钟才能实现.
  • 你的内容会有一个错误(特别是如果你复制粘贴了实现)

反对Objects.hash

  • Java 文档没有对散列交叉兼容性做出任何承诺(JVM v6和JVM v8是否会提供相同的值?总是在OS上?)
  • 关于hashCodes的事情,如果"均匀分布",它们效果最好.因此,如果int值仅对范围1到100有效,您可能希望"重新分配"其哈希代码,而不是所有哈希代码都属于同一个存储桶.
  • 如果您有任何要求让您质疑Objects.hash如何工作,可靠性/性能明智,请仔细考虑哈希码是否真正符合您的需求,并实现满足需求的自定义哈希编码方法.


Iho*_* M. 7

Joshua Bloch 在他的《Effective Java》一书中,第 3 版,p。53 不鼓励使用Objects.hash(...)if 性能至关重要。

原语被自动装箱,创建Object数组会受到惩罚。