简体   繁体   English

如果 hashcode() 是根据 object 的地址创建 hashcode 的,那么两个内容相同的不同对象如何创建相同的 hashcode?

[英]If the hashcode() creates hashcode based on the address of the object, how can two different objects with same contents create the same hashcode?

When you read the description of hashCode() in the Object class, it says that当您阅读 Object class 中的 hashCode() 描述时,它说

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.如果两个对象根据 equals(Object) 方法相等,则对两个对象中的每一个调用 hashCode 方法必须产生相同的 integer 结果。

I've read an article and it says that an object's hashcode() can provide different integer values if it runs in different environments even though their content is the same.我读过一篇文章,它说如果对象的 hashcode() 在不同的环境中运行,即使它们的内容相同,它也可以提供不同的 integer 值。

It does not happen with String class's hashcode() because the String class's hashcode() creates integer value based on the content of the object. String 类的 hashcode() 不会发生这种情况,因为 String 类的 hashcode() 会根据 object 的内容创建 integer 值。 The same content always creates the same hash value.相同的内容总是创建相同的 hash 值。

However, it happens if the hash value of the object is calculated based on its address in the memory.但是,如果根据 memory 中的地址计算 object 的 hash 值,则会发生这种情况。 And the author of the article says that the Object class calculates the hash value of the object based on its address in the memory. And the author of the article says that the Object class calculates the hash value of the object based on its address in the memory.

In the example below, the objects, p1 and p2 have the same content so equals() on them returns true.在下面的示例中,对象 p1 和 p2 具有相同的内容,因此它们上的 equals() 返回 true。 However, how come these two objects return the same hash value when their memory addresses are different?但是,当它们的 memory 地址不同时,这两个对象为什么返回相同的 hash 值?

Here is the example code: main()这是示例代码: main()

 Person p1 = new Person2("David", 10);
 Person p2 = new Person2("David", 10);

 boolean b = p1.equals(p2);

 int hashCode1 = p1.hashCode();
 int hashCode2 = p2.hashCode();

Here is the overriden hashcode()这是覆盖的 hashcode()

 public int hashCode(){
       return Objects.hash(name, age);
 }

Is the article's content wrong?文章内容有错吗?

If there is a hashCode() that calculates a hash value based on the instance's address what is the purpose of them?如果有一个 hashCode() 根据实例的地址计算 hash 值,它们的目的是什么?

Also, if it really exists, it violates the condition that Object class's hashCode() specifies.此外,如果它确实存在,则它违反了 Object 类的 hashCode() 指定的条件。 How should we use the hashCode() then?那我们应该如何使用 hashCode() 呢?

Here's the design decision every programmer needs to make for objects they define of (say) MyClass:这是每个程序员需要为他们定义的(比如)MyClass 的对象做出的设计决策:

Do you want it to be possible for two different objects to be "equal"?您是否希望两个不同的对象可以“相等”?

If you do, then firstly you have to implement MyClass.equals() so that it gives the correct notion of equality for your purposes.如果你这样做,那么首先你必须实现 MyClass.equals() 以便它为你的目的提供正确的平等概念。 That's entirely in your hands.这完全在你的手中。

Then you're supposed to implement hashCode such that, if A.equals(B), then A.hashCode() == B.hashCode().然后你应该实现 hashCode,如果 A.equals(B),那么 A.hashCode() == B.hashCode()。 You explicitly do not want to use Object.hashCode().您明确不想使用 Object.hashCode()。

If you don't want different objects to ever be equal, then don't implement equals() or hashCode(), use the implementations that Object gives you.如果你不希望不同的对象永远相等,那么不要实现 equals() 或 hashCode(),使用 Object 给你的实现。 For Object A and Object B (different Objects, and not subclasses of Object), then it is never the case that A.equals(B), and so it's perfectly ok that A.hashCode() is never the same as B.hashCode().对于 Object A 和 Object B(不同的对象,而不是对象的子类),那么 A.equals(B) 绝不是这种情况,因此 A.hashCode() 绝不与 B.hashCode 相同()。

  1. The article is wrong, memory address is not involved (btw. the address can change during the lifecycle of objects, so it's abstracted away as a reference).文章错了,memory 地址没有涉及(顺便说一句,地址在对象的生命周期中会发生变化,所以抽象出来作为参考)。 You can look at the default hashCode as a method that returns a random integer, which is always the same for the same object.您可以将默认 hashCode 视为一种返回随机 integer 的方法,对于相同的 object,它始终相同。

  2. Default equals (inherited from Object ) works exactly like == .默认equals (从Object继承)的工作方式与==完全相同。 Since there is a condition (required for classes like HashSet etc. to work) that states when a.equals(b) then a.hashCode == b.hashCode , then we need a default hashCode which only has to have one property: when we call it twice, it must return the same number.由于有一个条件( HashSet等类工作所必需的)说明当 a.equals(b) 然后 a.hashCode == b.hashCode时,我们需要一个默认的hashCode ,它只需要一个属性:when我们调用它两次,它必须返回相同的数字。

  3. The default hashCode exists exactly so that the condition you mention is upheld.默认 hashCode 完全存在,因此您提到的条件得到支持。 The value returned is not important, it's only important that it never changes.返回的值并不重要,重要的是它永远不会改变。

No p1 and p2 does not have the same content没有 p1 和 p2 没有相同的内容

If you do p1.equals(p2) that will be false, so not the same content.如果你这样做 p1.equals(p2) 那将是错误的,所以内容不一样。

If you want p1 and p2 to equal, you need to implement the equals methods from object, in a way that compare their content.如果希望 p1 和 p2 相等,则需要实现 object 中的 equals 方法,以比较它们的内容。 And IF you implement the equals method, then you also MUST implement the hashCode method, so that if equals return true, then the objects have the same hashCode().如果你实现了equals方法,那么你也必须实现hashCode方法,这样如果equals返回true,那么对象就有相同的hashCode()。

I think you have misunderstood this statement:我想你误解了这个说法:

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.如果两个对象根据 equals(Object) 方法相等,则对两个对象中的每一个调用 hashCode 方法必须产生相同的 integer 结果。

The word “must” means that you, the programmer, are required to write a hashCode() method which always produces the same hashCode value for two objects which are equal to each other according to their equals(Object) method. “必须”这个词意味着你,程序员,需要编写一个hashCode()方法,该方法总是为两个根据equals(Object)方法彼此相等的对象生成相同的 hashCode 值。

If you don't, you have written a broken object that will not work with any class that uses hash codes, particularly unsorted Sets and Maps.如果你不这样做,你写了一个损坏的 object,它不能与任何使用 hash 代码的 class 一起工作,特别是未排序的集合和映射。

I've read an article and it says that an object's hashcode() can provide different integer values if it runs in different environments even though their content is the same.我读过一篇文章,它说如果对象的 hashcode() 在不同的环境中运行,即使它们的内容相同,它也可以提供不同的 integer 值。

Yes, hashCode() can provide different values in different runtimes, for a class which does not override the hashCode() method.是的,对于不覆盖 hashCode() 方法的 class ,hashCode()可以在不同的运行时提供不同的值。

… how come these two objects return the same hash value when their memory addresses are different? ... 为什么这两个对象的 memory 地址不同时返回相同的 hash 值?

Because you told them to.因为你告诉他们。 You overrode the hashCode() method.您覆盖了hashCode()方法。

If there is a hashCode() that calculates a hash value based on the instance's address what is the purpose of them?如果有一个 hashCode() 根据实例的地址计算 hash 值,它们的目的是什么?

It doesn't have a lot of use.它没有太多用处。 That's why programmers are strongly recommended to override the method, unless they don't care about object identity.这就是为什么强烈建议程序员重写该方法的原因,除非他们不关心 object 身份。

Also, if it really exists, it violates the condition that Object class's hashCode() specifies.此外,如果它确实存在,则它违反了 Object 类的 hashCode() 指定的条件。 How should we use the hashCode() then?那我们应该如何使用 hashCode() 呢?

No it does not.不,不是的。 The contract states : 合同规定

  • 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. 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. This integer need not remain consistent from one execution of an application to another execution of the same application.此 integer 不需要从应用程序的一次执行到同一应用程序的另一次执行保持一致。

As long as the hashCode method defined in the Object class returns the same value for the duration of the Java runtime, it is compliant.只要在 Object class 中定义的 hashCode 方法在 Java 运行时期间返回相同的值,它就是合规的。

The contract also says:合同还说:

  • 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.如果两个对象根据equals(Object)方法相等,则对两个对象中的每一个调用hashCode方法必须产生相同的 integer 结果。

Two objects whose equals method reports that they are effectively equal must return the same hashCode.其 equals 方法报告它们实际上相等的两个对象必须返回相同的 hashCode。 Any instance of the Object class whose type is not a subclass of Object is only equal to itself and cannot be equal to any other object, so any value it returns is valid, as long as it is consistent throughout the life of the Java runtime. Any instance of the Object class whose type is not a subclass of Object is only equal to itself and cannot be equal to any other object, so any value it returns is valid, as long as it is consistent throughout the life of the Java runtime.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM