快速问题:如果我想使用HashMap
自定义类作为键,我必须重写该hashCode
函数吗?如果我不覆盖该功能,它将如何工作?
6 回答
如果您不覆盖 hashCode AND equals 您将获得默认行为,即每个对象都是不同的,无论其内容如何。
从技术上讲,只要相等的对象具有相同的 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 方法结果的方式更改键对象,否则地图将找不到您的值了。这就是为什么建议尽可能使用不可变对象作为键的原因。
唯一不需要覆盖hashCode()
函数的时候是你也没有覆盖equals
,所以你使用Object.equals
引用相等的默认定义。这可能是也可能不是您想要的——特别是,即使它们具有相同的字段值,不同的对象也不会被视为相等。
如果你覆盖equals
但不覆盖hashCode
,HashMap
行为将是未定义的(阅读:它根本没有任何意义,并且将被完全破坏)。
这取决于您用作键的对象类。如果它是您建议的自定义类,并且它不扩展任何东西(即它 extends Object
),那么 hashCode 函数将是 of Object
,并且将考虑内存引用,使两个看起来相同的对象散列到不同的代码.
所以是的,除非您使用您知道对您有用的功能扩展一个类,否则您hashCode()
需要实现自己的功能。还要确保实现equals()
:像 HashMap 这样的一些类ArrayList
只会使用 equals,而像 HashMap 这样的类会同时检查hashCode()
和equals()
。
还要考虑一下,如果您的密钥不是不可变的,您可能会遇到问题。如果您在映射中放置一个带有可变键的条目,然后您以影响哈希码和等于的方式更改键,您可能会丢失映射中的条目,因为您将无法再检索它。
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
- If a class overrides
equals()
, it must overridehashCode()
. - If 2 objects are equal, then their
hashCode
values must be equal as well. - If a field is not used in
equals()
, then it must not be used inhashCode()
. - If it is accessed often,
hashCode()
is a candidate for caching to enhance performance.