8

快速问题:如果我想使用HashMap自定义类作为键,我必须重写该hashCode函数吗?如果我不覆盖该功能,它将如何工作?

4

6 回答 6

5

如果您不覆盖 hashCode AND equals 您将获得默认行为,即每个对象都是不同的,无论其内容如何。

于 2012-07-01T10:21:15.387 回答
4

从技术上讲,只要相等的对象具有相同的 hashCode,您就不必重写 hashCode 方法。

因此,如果您使用 Object 定义的默认行为,其中 equals 仅针对同一实例返回 true,那么您不必重写 hashCode 方法。

但是,如果您不覆盖 equals 和 hashCode 方法,则意味着您必须确保始终使用相同的键实例。

例如:

MyKey key1_1 = new MyKey("key1");

myMap.put(key1_1,someValue); // OK

someValue = myMap.get(key1_1); // returns the correct value, since the same key instance has been used;

MyKey key1_2  = new MaKey("key1"); // different key instance

someValue = myMap.get(key1_2); // returns null, because key1_2 has a different hashCode than key1_1 and key1_1.equals(key1_2) == false

实际上,您通常只有一个键实例,因此从技术上讲,您不必重写 equals 和 hashCode 方法。

但最好的做法是覆盖用作键的类的 equals 和 hashCode 方法,因为稍后您或其他开发人员可能会忘记必须使用相同的实例,这可能导致难以跟踪问题。

请注意:即使您覆盖了 equals 和 hashCode 方法,也必须确保不会以会更改 equals 或 hashCode 方法结果的方式更改键对象,否则地图将找不到您的值了。这就是为什么建议尽可能使用不可变对象作为键的原因。

于 2012-07-01T11:41:49.800 回答
4

唯一不需要覆盖hashCode()函数的时候是你也没有覆盖equals,所以你使用Object.equals引用相等的默认定义。这可能是也可能不是您想要的——特别是,即使它们具有相同的字段值,不同的对象也不会被视为相等。

如果你覆盖equals但不覆盖hashCodeHashMap行为将是未定义的(阅读:它根本没有任何意义,并且将被完全破坏)。

于 2012-07-01T10:20:29.273 回答
3

这取决于您用作键的对象类。如果它是您建议的自定义类,并且它不扩展任何东西(即它 extends Object),那么 hashCode 函数将是 of Object,并且将考虑内存引用,使两个看起来相同的对象散列到不同的代码.

所以是的,除非您使用您知道对您有用的功能扩展一个类,否则您hashCode()需要实现自己的功能。还要确保实现equals():像 HashMap 这样的一些类ArrayList只会使用 equals,而像 HashMap 这样的类会同时检查hashCode()equals()

于 2012-07-01T10:21:37.017 回答
0

还要考虑一下,如果您的密钥不是不可变的,您可能会遇到问题。如果您在映射中放置一个带有可变键的条目,然后您以影响哈希码和等于的方式更改键,您可能会丢失映射中的条目,因为您将无法再检索它。

于 2012-07-01T11:28:01.803 回答
0

You should override the equals() and hashCode() methods from the Object class. The default implementation of the equals() and hashcode(), which are inherited from the java.lang.Object uses an object instance’s memory location (e.g. MyObject@6c60f2ea). This can cause problems when two instances of the an objects have the same properties but the inherited equals() will return false because it uses the memory location, which is different for the two instances.

Also the toString() method can be overridden to provide a proper string representation of your object.

primary considerations when implementing a user defined key

  1. If a class overrides equals(), it must override hashCode().
  2. If 2 objects are equal, then their hashCode values must be equal as well.
  3. If a field is not used in equals(), then it must not be used in hashCode().
  4. If it is accessed often, hashCode() is a candidate for caching to enhance performance.
于 2013-04-07T09:05:24.130 回答