gpt4 book ai didi

java - 哈希码的默认实现为以相同方式构造的对象返回不同的值

转载 作者:搜寻专家 更新时间:2023-11-01 01:00:30 24 4
gpt4 key购买 nike

这里我写了一个示例代码:

public class Test {

private int i;
private int j;

public Test() {
// TODO Auto-generated constructor stub
}

public Test(int i, int j)
{
this.i=i;
this.j=j;
}
}

现在我正在创建如下两个对象:

Test t1= new Test(4,5);
Test t2 = new Test(4,5);

但是当我打印 t1.hashcode() 和 t2.hashcode() 时,它们给出了不同的值。但是根据 java 的一般联系,它们应该返回相同的值。事实上,当我对 String 或 Integer 做同样的事情时,它们返回相同的 hashcode()。谁能解释为什么 t1 和 t2 对象的哈希码不同?

最佳答案

But as per java's general contact they should return same value.

Java 的equals-hashCode 契约要求如果两个对象等于Object.equals ,它们必须具有来自 Object.hashCode 的相同哈希码.但是 Object.equals默认实现是引用相等性,因此当且仅当它们是同一实例时,两个实例才相同。

因此,特别是,您的两个实例 t1t2 实际上 相等,因为您没有覆盖 Object。等于。它们作为引用不相等,因此根据 Object.equals 不相等,因此 hashCode 可能返回不同的值是可以接受的。事实上,契约(Contract)明确规定如下:

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.

因此,我们在这里没有违反 equals-hashCode 约定。

因此,对于您的对象,如果您希望不同的实例根据相等的逻辑定义相等,则需要重写 Object.equals:

 @Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
if (this == obj) {
return true;
}
if (!(obj instanceof Test)) {
return false;
}
Test other = (Test)obj;
return this.i == other.i && this.j == other.j;
}

并且 equals-hashCode 契约要求您也覆盖 Object.hashCode 否则您会遇到一些讨厌的错误:

 @Override
public int hashCode() {
int hash = 17;
hash = 31 * hash + this.i;
hash = 31 * hash + this.j;
return hash;
}

契约(Contract)是怎么说的:

If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.

让我们看看这里是否满足了这个要求。如果 xyTest 的实例并且满足 x.equals(y)true,我们有 x.i == y.ix.j == y.j。然后,很明显,如果我们调用 x.hashCode()y.hashCode(),我们在 Test.hashCode< 中的每一行执行中都有不变量 我们将拥有包含相同值的 hash。显然这在第一行是正确的,因为在这两种情况下 hash 都是 17。它将保留在第二行,因为 this.i 将返回相同的值,无论是 this == x 还是 this == y 因为 x.i 等于 y.i。最后,在倒数第二行,我们仍然会让 hash 在两次调用中都相等,因为 x.j 等于 y.j 也是真的。

请注意,还有最后一项我们尚未讨论的契约(Contract)。这是 hashCode 在 Java 应用程序的单次执行期间返回一致值的要求:

Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified.

这样做的必要性是显而易见的。如果在同一应用程序的单次执行期间更改 hashCode 的返回值,您可能会在使用 hashCode 跟踪对象的类似哈希表的数据结构中丢失对象.特别是,这就是为什么在类似哈希表的数据结构中改变作为键的对象是纯粹的邪恶;不要这样做。我什至会争辩说它们应该是不可变的对象。

In fact, when i am doing same thing with String or Integer they are returning same hashcode().

它们都覆盖了 Object.equalsObject.hashCode

关于java - 哈希码的默认实现为以相同方式构造的对象返回不同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17159881/

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