在Java的Hashmap中将自定义类设置为键值对

17

我有一个类,我想将它设置为HashMap中的键。我已经为该类实现了compareTo方法。但是当我执行以下代码时:

map.put(new MyKey(dummyArguements) , dummyValue );
System.out.println(map.get( new MyKey(dummyArguements) ) );

结果输出为null,这意味着HashMap没有识别出两个键(对于get和put调用)是相同的。

请问有人可以帮我解决这个问题吗?

7个回答

40

您需要实现hashCode()equals()方法。对于排序的映射/集合,还需要实现compareTo()方法。

请参见此问题了解详细信息。


1
我并不是不相信这是真的,也不是有任何不尊重的意思,但是您是如何知道这一点的呢?我已经反复阅读了 HashMap 的文档,遵循接口和继承……但是没有任何迹象表明上述方法需要被实现或覆盖(因为它们已经从 Object 根类中继承)才能使其与 HashMap 正常工作。 - user1040049
Map接口上一些方法的定义建立了一些规则。例如containsKey()明确提到equals()。Object上hashCode()方法的文档指定了它与equals()之间的关系。我同意你的观点- HashMap的文档应该引用hashCode()方法,并记录它作为HashMap键的使用/要求。 - Mike Q
你的类应该是“不可变的”。 - Sadegh

13

你应该实现 equals()hashCode() 方法。你的类也应该是不可变的,如果它是可变的,在将其添加到 Map 中后,它的哈希码可能会发生变化。然后,Map 可能无法正确地找到它。


他在putadd之前进行了新的操作。因此,不可变性并不重要。仍然是一个很好的观点,+1。 - fastcodejava

3

1) 通常情况下,对于集合类而言,您需要重写类的equals()方法(以及hashcode()方法)。compareTo()/Comparable和Comparator通常用于排序,并且只在某些情况下替代equals()方法用于对象等价性 - 例如SortedSet的实现者,如TreeSet。

2) 请在您的代码中遵守Java命名规范。您的类名应该大写...例如new MyKey(dummyArguments)。详见http://www.oracle.com/technetwork/java/codeconventions-135099.html#367(以及http://www.oracle.com/technetwork/java/codeconvtoc-136057.html)。


0
从Java8开始,您还应该实现Comparable(添加compareTo),因为如果哈希碰撞的数量超过11个,则HashMap会将条目存储在二叉树中。如果不这样做,性能将受到影响。

0
你是否已经定义了hashCode()?排序需要使用compareTo

0

HashMap 不会检查 compareTo()

HashMap 会检查 hashCode()equals()


0

当使用依赖哈希的集合(如Map和Set)时,您必须实现equals()hashCode()以确保正确的功能。如果您不这样做,新的myKey将始终与存储在映射中的键不同,因为它使用equals()hashCode()的默认实现。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接