Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/397.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 从equals()调用hashCode()_Java_Equals_Hashcode - Fatal编程技术网

Java 从equals()调用hashCode()

Java 从equals()调用hashCode(),java,equals,hashcode,Java,Equals,Hashcode,我已经为我的类定义了hashCode(),并列出了一长串的类属性 根据契约,我还需要实现equals(),但是否可以通过比较内部的hashCode()来实现它,以避免所有额外的代码?这样做有危险吗 e、 g 不要那样做 hashCode()的契约规定,相等的两个对象必须具有相同的hashCode。对于不相等的对象,它不能保证任何东西。这意味着您可能有两个完全不同的对象,但碰巧有相同的hashcode,从而破坏了您的equals() 获取字符串之间的哈希代码冲突并不难。考虑JDK 8实现中的核心循

我已经为我的类定义了
hashCode()
,并列出了一长串的类属性

根据契约,我还需要实现equals(),但是否可以通过比较内部的
hashCode()
来实现它,以避免所有额外的代码?这样做有危险吗

e、 g

不要那样做

hashCode()
的契约规定,相等的两个对象必须具有相同的hashCode。对于不相等的对象,它不能保证任何东西。这意味着您可能有两个完全不同的对象,但碰巧有相同的hashcode,从而破坏了您的
equals()

获取字符串之间的哈希代码冲突并不难。考虑JDK 8实现中的核心循环:

for (int i = 0; i < value.length; i++) {
    h = 31 * h + val[i];
}
如果我们选择任意字符串,如
“abZ”
,我们有:

h("abZ") = 31 * (31 * 'a' + 'b') + 'Z'
h("abZ") = 31 * (31 * 97 + 98) + 90
h("abZ") = 96345
然后我们可以从
val[1]
中减去
1
,同时将
31
添加到
val[2]
,这就得到了字符串
“aay”

导致冲突:
h(“abZ”)==h(“aay”)==96345

另外,请注意,
equals()
实现不会检查您是否正在比较相同类型的对象。因此,假设您有
this.hashCode()==96345
,下面的语句将返回
true

yourObject.equals(Integer.valueOf(96345))

这可能不是您想要的。

仅比较对象的
hashCode()
是绝对不安全的

您的对象可以具有比哈希代码更多的不同状态:哈希代码是一个
int
,这意味着它被限制为2^32=4294967296个可能的值,但您的对象可能有多个
int
字段

因此,事实证明,可能有两个不同的对象(根据等式)具有相同的哈希代码


但当然,出于性能原因,您可以首先比较哈希代码(如果哈希代码计算比字段比较快):如果哈希代码不相等,则对象也不相等,因此您可以安全地立即返回
false

当您遇到哈希代码冲突时会发生什么情况?除非您有一个双射哈希代码函数(这不太可能),否则这不是实现equals的好方法。正如@resueman所说,如果发生冲突,最终会导致两个不同的对象相等,因为它们具有相同的hashcode值。另外,equals方法不会检查正在比较的实例是否具有相同的类型,您可以将实例与具有相同hashcode值的字符串进行比较,结果将返回true。我想这肯定不是你想要的……如果两个对象根据equals()方法是相等的,那么它们必须具有相同的hashCode()值,但反过来通常不是真的。因此,不建议通过比较hashcode()来实现equals()。值得注意的是,即使在这种方法有效的情况下,您的实现也会失败,因为它不会检查对象是否为相同的类型。您应该了解一下。这将为您生成
#equals()
#hashCode()
#toString()
,因此您不必关心这些。谢谢,但在哪种情况下会发生变化?如果我所有的字段都是字符串,我在技术上是否安全?(但我明白我一般不应该这么做)@dystroy公平的假设,因为OP正在使用
HashCodeBuilder
构建一个hashcode,该hashcode指向不强制hash函数双射性的commons类。@geneb。不,字符串容易发生大量哈希冲突。如果对象的可能值超过2^32,则必然会发生哈希冲突。有超过2^32个可能的字符串。谢谢,我想问一下,如果hashCode()不能保证区分,为什么还需要它,但我现在看到它用于集合中的快速contains()查找,只有在找到多个对象时,才会使用equals()来区分。
h("abZ") = 31 * (31 * 'a' + 'b') + 'Z'
h("abZ") = 31 * (31 * 97 + 98) + 90
h("abZ") = 96345
h("aay") = 31 * (31 * 'a' + 'a') + 'y'
h("aay") = 31 * (31 * 97 + 97) + 121
h("aay") = 96345
yourObject.equals(Integer.valueOf(96345))