Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/kubernetes/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Objects.hash()还是自己的hashCode()实现?_Java_Hash - Fatal编程技术网

Java 使用Objects.hash()还是自己的hashCode()实现?

Java 使用Objects.hash()还是自己的hashCode()实现?,java,hash,Java,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 >&

我最近发现了这个方法

我的第一个想法是,这会大大整理您的
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);
}
虽然我不得不说,这似乎太好了,不可能是真的。我也从未见过这种用法

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

更新


尽管此主题标记为已解决,但请随时发布提供新信息和关注点的答案。

请注意
对象的参数。散列
对象…
。这有两个主要后果:

  • 散列码计算中使用的原语值必须装箱,例如,
    此.id
    long
    转换为
    long
  • 必须创建一个
    对象[]
    ,以调用该方法

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

以下是对象的实现。hash-在内部调用Arrays.hashCode

public static int hash(Object... values) {
    return Arrays.hashCode(values);
}
这是数组.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;
}
所以我同意@Andy的观点
如果频繁调用hashCode,创建这些“不必要”对象的成本可能会增加。如果你自己实施,它会更快。

我想试着为这两种方法做一个有力的论证

开场白免责声明 对于这个答案,
Objects.hash()
Objects.hashCode()
,以及任何执行此角色的库提供的任何函数都是可互换的。首先,我想说的是,使用
Objects.hash()
,或者根本不使用静态对象函数。任何支持或反对此方法的论点都需要对编译后的代码进行假设,但这些假设不能保证为真。(例如,编译器优化器可能会将函数调用转换为内联调用,从而绕过额外的调用堆栈和对象分配。就像没有任何用处的循环不会进入编译版本一样(除非关闭优化器)。您也无法保证将来的Java版本不会像C#一样在其方法版本中包含JVM版本。(出于安全原因,我相信))因此,关于使用此函数,您可以提出的唯一安全论点,通常,将适当哈希的细节留给此函数比尝试实现自己的原始版本更安全

对于Objects.hash
  • 保证是一个好的散列
  • 实施需要5秒钟
  • 您的可能有一个bug(特别是如果您复制粘贴了实现)
针对Objects.hash
  • Java没有承诺哈希交叉兼容性(JVMV6和JVMV8会给出相同的值吗?总是?跨操作系统?)
  • 最重要的是,如果“均匀分布”,它们的效果最好。因此,如果一个int值仅对范围1到100有效,那么您可能希望“重新分配”其哈希代码,使其不都是同一个bucket的一部分
  • 如果您有任何要求让您质疑Objects.hash如何工作,从可靠性/性能角度考虑,请仔细考虑hash代码是否真的是您想要的,并实现一种自定义hash编码方法,以满足您的需求

约书亚·布洛赫(Joshua Bloch)在其著作《有效的Java》第三版第。53如果性能至关重要,则不鼓励使用
对象。哈希(…)


原语将被自动装箱,创建
对象
数组将受到惩罚

就我个人而言,我会首先选择简短的代码,因为阅读、更改和验证代码要快得多,因为它们都是正确的,在修改类时可以避免错误

然后,对于性能关键类或散列成本较高的字段,我将缓存结果(如
String
does):

在这种无锁线程安全模式中(它自然假设一个不可变的类),
hash
可能会被不同的线程多次初始化,但这并不重要,因为public方法的结果总是相同的。(内存可见性)正确性的关键是确保方法中的
hash
不会被多次写入和读取


一旦代码得到JIT内联并由C2编译器优化,则
Objects.hash的数组构造代价可能会比您想象的要低。幸运的是,优秀的JDK人员有一些基本上可以消除使用它的所有开销的东西:

另请参见
HashCodeBulider
:但是commons builder使用反射。它很方便,但绝对是性能杀手。@NPE我真的想把它留给当地人。我不太喜欢外部apache common Stuff Use Lombok和
@EqualsAndHashCode
@MartinSchröder,谢谢,但我想保持我的依赖关系。与所有性能问题一样,你应该向自己证明,你先关心后关心。@CandiedOrange yes;另一方面,不要编写您可能需要关心的代码。我的意思是,您可以使用
返回0来实现
hashCode
如果你不关心性能,除非你已经证明不是这样。由于您只需编写一次,而且IDE很可能会为您生成代码,因此您最好选择详细但性能良好的版本。但我不会急于将现有代码中的任何一种形式更改为另一种形式。您在这里指的是
对象。hashCode
:您的意思是这样做,还是指
对象。hash
(这就是OP所问的)?@而且就我在这个答案中真正关心的问题而言,任何库提供的哈希函数都是可互换的,不会真正影响点。如果你真的在乎这两者之间的区别,你会怎么做
// volatile not required for 32-bit sized primitives
private int hash;

@Override
public final int hashCode() {
    // "Racy Single-check idiom" (Item 71, Effective Java 2nd ed.)
    int h = hash;
    if (h == 0) {
        h = Objects.hash(id, timestamp, severity, thread, classPath, message);
        hash = h;
    }
    return h;
}