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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 04:30:40  来源:igfitidea点击:

Using HashMap with custom key

javamap

提问by MBZ

Quick Question: If I want to use HashMapwith a custom class as the key, mustI override the hashCodefunction? 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.equalsdefinition 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 equalsbut not hashCode, HashMapbehavior 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 ArrayListwill 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.Objectuses 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 falsebecause 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

实现用户定义的键时的主要考虑因素

  1. If a class overrides equals(), it must override hashCode().
  2. If 2 objects are equal, then their hashCodevalues 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.
  1. 如果一个类覆盖equals(),它必须覆盖hashCode()
  2. 如果 2 个对象相等,则它们的hashCode值也必须相等。
  3. 如果某个字段未在 中使用equals(),则不得在 中使用hashCode()
  4. 如果经常访问,hashCode()则是缓存以提高性能的候选者。