gpt4 book ai didi

c# - 将对象的哈希码定义为所有类变量哈希码的总和、乘法等等是不正确的吗?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:11:31 25 4
gpt4 key购买 nike

假设我有以下类(class):

class ABC {
private int myInt = 1;
private double myDouble = 2;
private String myString = "123";
private SomeRandomClass1 myRandomClass1 = new ...
private SomeRandomClass2 myRandomClass2 = new ...

//pseudo code
public int myHashCode() {
return 37 *
myInt.hashcode() *
myDouble.hashCode() *
... *
myRandomClass.hashcode()
}
}

这会是 hashCode 的正确实现吗?这不是我通常的做法(我倾向于遵循 Effective Java 的指南),但我总是忍不住想做类似上面代码的事情。

谢谢

最佳答案

这取决于你所说的“正确”是什么意思。假设您正在使用所有相关 equals() 定义字段的 hashCode(),那么是的,它是“正确的”。然而,这样的公式可能不会有良好的分布,因此可能会导致比其他方式更多的冲突,这会对性能产生不利影响。

引用自 Effective Java 2nd Edition,第 9 条:在覆盖 equals 时始终覆盖 hashCode

While the recipe in this item yields reasonably good hash functions, it does not yield state-of-the-art hash functions, nor do Java platform libraries provide such hash functions as of release 1.6. Writing such hash functions is a research topic, best left to mathematicians and computer scientists. [...Nonetheless,] the techniques described in this item should be adequate for most applications.

可能不需要大量的数学能力来评估您提出的哈希函数有多好,但为什么还要费心呢?为什么不只遵循在实践中被证明足够的东西呢?

乔什·布洛赫的食谱

  • 在名为 resultint 变量中存储一些常量非零值,比如 17。
  • 为每个字段计算一个int哈希码c:
    • 如果该字段是一个 boolean 值,计算(f ? 1 : 0)
    • 如果字段是byte, char, short, int,计算(int) f
    • 如果字段是long,计算(int) (f ^ (f >>> 32))
    • 如果字段是float,计算Float.floatToIntBits(f)
    • 如果该字段是一个double,计算Double.doubleToLongBits(f),然后像上面那样散列结果long。<
    • 如果该字段是一个对象引用,并且该类的equals 方法通过递归调用equals 来比较该字段,则递归调用该字段的hashCode .如果该字段的值为null,则返回0。
    • 如果该字段是一个数组,则将其视为每个元素都是一个单独的字段。如果数组字段中的每个元素都很重要,您可以使用 1.5 版中添加的 Arrays.hashCode 方法之一。
  • 将哈希码c合并成result,如下:result = 31 * result + c;

现在,当然这个配方相当复杂,但幸运的是,你不必每次都重新实现它,多亏了java.util.Arrays.hashCode(Object[]) (并且 com.google.common.base.Objects 提供了一个方便的 vararg 变体)。

@Override public int hashCode() {
return Arrays.hashCode(new Object[] {
myInt, //auto-boxed
myDouble, //auto-boxed
myRandomClass,
});
}

另见

  • Object.hashCode()

    It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.

关于c# - 将对象的哈希码定义为所有类变量哈希码的总和、乘法等等是不正确的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2735037/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com