使用HashMap的自定义键(Using HashMap with custom key)

2019-07-30 04:51发布

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

Answer 1:

从技术上讲,你不必,只要相等的对象有相同的hashCode覆盖hashCode方法。

所以,如果你使用的对象,其中定义等于默认行为只能针对相同的实例返回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方法的结果的关键对象,否则地图将无法找到自己的价值了。 这就是为什么我们建议尽可能使用不可变对象作为键。



Answer 2:

如果不重写了hashCode和equals你会得到默认行为是每个对象是不同的,无论其内容。



Answer 3:

唯一的一次,你不必重写hashCode()函数是当你还没有覆盖equals ,让你使用默认Object.equals参考平等的定义。 这可能是也可能不是你想要的-特别是,不同的对象将不会被认为是相等的,即使他们有相同的字段值。

如果重写equals但不hashCodeHashMap行为将是不确定的(阅读:它不会使任何意义,并会完全损坏)。



Answer 4:

这取决于你所使用作为重点对象类。 如果它是一个自定义类,像你这样的建议,并没有延伸任何东西(即它扩展Object ),那么哈希码功能将是的Object ,并会考虑内存的引用,使得看起来你返回相同的两个对象不同的代码。

所以,是的,除非你是扩展一个类具有hashCode()函数,你知道你的作品,你需要实现自己的。 另外,还要确保实现equals() :有的类,如ArrayList只使用相当于而其他类似的HashMap将检查两个hashCode()equals()



Answer 5:

想想也是,如果你的关键并不是一成不变的,你可能有问题。 如果你把一个可变键的条目在地图上的更改后的方式,它会影响哈希码,等于你可能会失去在地图上您的项目,你将无法再检索它的关键。



Answer 6:

你应该重写equals()hashCode()从Object类的方法。 在默认的实现equals()hashcode() ,这是从继承java.lang.Object使用一个对象实例的存储位置(例如MyObject@6c60f2ea )。 这可能会导致问题,当一个对象的两个实例具有相同的属性,但继承的equals()将返回false ,因为它使用的memory location ,这是两个不同的实例。

还有toString()方法可以被重写以提供您的对象的适当的字符串表示。

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

  1. 如果一个类重写equals()它必须覆盖hashCode()
  2. 如果2个对象是相等的,那么它们hashCode值必须相等。
  3. 如果某个字段是不是在使用equals() ,那么就不能在使用hashCode()
  4. 如果是经常访问hashCode()是用于缓存以提高性能的候选人。


文章来源: Using HashMap with custom key
标签: java map