java 使用带有自定义键的 HashMap
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11281166/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using HashMap with custom key
提问by MBZ
Quick Question: If I want to use HashMap
with a custom class as the key, mustI override the hashCode
function? How will it work if I do not override that function?
快速问题:如果我想使用HashMap
自定义类作为键,是否必须覆盖该hashCode
函数?如果我不覆盖该功能,它将如何工作?
采纳答案by Puce
Technically, you don't have to override the hashCode method as long as equal objects have the same hashCode.
从技术上讲,只要相等的对象具有相同的 hashCode,就不必覆盖 hashCode 方法。
So, if you use the default behaviour defined by Object, where equals only returns true only for the same instance, then you don't have to override the hashCode method.
因此,如果您使用 Object 定义的默认行为,其中 equals 仅对同一实例返回 true,那么您不必覆盖 hashCode 方法。
But if you don't override the equals and the hashCode methods, it means you have to make sure you're always using the same key instance.
但是,如果您不覆盖 equals 和 hashCode 方法,则意味着您必须确保始终使用相同的键实例。
E.g.:
例如:
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
In practice you often have only one instance of the key, so technically you don't have to override the equals and hashCode methods.
实际上,您通常只有一个密钥实例,因此从技术上讲,您不必覆盖 equals 和 hashCode 方法。
But it's best practice to override the equals and hashCode methods for classes used as keys anyway, because sometime later you or another developer might forget that the same instance has to be used, which can lead to hard to track issues.
但是最好的做法是覆盖用作键的类的 equals 和 hashCode 方法,因为稍后您或其他开发人员可能会忘记必须使用相同的实例,这会导致难以跟踪的问题。
And note: even if you override the equals and hashCode methods, you must make sure you don't change the key object in a way that would change the result of the equals or the hashCode methods, otherwise the map won't find your value anymore. That's why it's recommended to use immutable objects as keys if possible.
并注意:即使您覆盖了 equals 和 hashCode 方法,您也必须确保不会以会更改 equals 或 hashCode 方法的结果的方式更改键对象,否则映射将找不到您的值了。这就是为什么建议尽可能使用不可变对象作为键的原因。
回答by Peter Lawrey
If you don't override hashCode AND equals you will get the default behaviour which is that each object is different, regardless of its contents.
如果您不覆盖 hashCode AND equals,您将获得默认行为,即每个对象都不同,无论其内容如何。
回答by Louis Wasserman
The only time you don't have to override the hashCode()
function is when you also don't override equals
, so you use the default Object.equals
definition of reference equality. This may or may not be what you want -- in particular, different objects will notbe considered equal even if they have the same field values.
唯一不需要覆盖该hashCode()
函数的情况是您也没有覆盖equals
,因此您使用Object.equals
引用相等的默认定义。这可能是您想要的,也可能不是您想要的——特别是,即使不同的对象具有相同的字段值,它们也不会被视为相等。
If you override equals
but not hashCode
, HashMap
behavior will be undefined (read: it won't make any sense at all, and will be totally corrupted).
如果您覆盖equals
但不覆盖hashCode
,则HashMap
行为将是未定义的(阅读:它根本没有任何意义,并且会完全损坏)。
回答by Miquel
It depends on the object class you are using as a key. If it's a custom class like you propose, and it doesn't extend anything (i.e. it extends Object
) then the hashCode function will be that of Object
, and that will consider memory references, making two objects that look the same to you hash to different codes.
这取决于您用作键的对象类。如果它是您提议的自定义类,并且它不扩展任何内容(即它扩展Object
),那么 hashCode 函数将是 of Object
,并且会考虑内存引用,使两个看起来相同的对象散列到不同的代码.
So yes, unless you are extending a class with a hashCode()
function you know works for you, you need to implement your own. Also make sure to implement equals()
: some classes like ArrayList
will only use equals while others like HashMap will check on both hashCode()
and equals()
.
所以是的,除非你使用一个hashCode()
你知道对你有用的函数来扩展一个类,否则你需要实现你自己的。还要确保实现equals()
:ArrayList
像 HashMap这样的一些类将只使用 equals 而其他类将检查hashCode()
和equals()
。
回答by JayZee
Consider also that if your key is not immutable you may have problems. If you put an entry with a mutable key in the map an you change later the key in a way that it affects hashcode and equals you may lose your entry in the map,as you won't be able to retrieve it anymore.
还要考虑的是,如果您的密钥不是不可变的,您可能会遇到问题。如果您在地图中放置了一个带有可变键的条目,并且您稍后会以影响哈希码和等于的方式更改该键,那么您可能会丢失地图中的条目,因为您将无法再检索它。
回答by Rupesh
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.
您应该覆盖Object 类中的equals()
和hashCode()
方法。的默认实现equals()
和hashcode()
,这是从继承java.lang.Object
使用一个对象实例的存储位置(例如MyObject@6c60f2ea
)。当 an 对象的两个实例具有相同的属性但继承的对象equals()
将返回时,这可能会导致问题,false
因为它使用memory location
了两个实例不同的 。
Also the toString()
method can be overridden to provide a proper string representation of your object.
此外,该toString()
方法可以被覆盖以提供对象的正确字符串表示。
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.
- 如果一个类覆盖
equals()
,它必须覆盖hashCode()
。 - 如果 2 个对象相等,则它们的
hashCode
值也必须相等。 - 如果某个字段未在 中使用
equals()
,则不得在 中使用hashCode()
。 - 如果经常访问,
hashCode()
则是缓存以提高性能的候选者。