如何使用自定义键类型使HashMap正常工作?

时间:2013-02-23 09:54:49

标签: java types hashmap key

我认为我的问题很简单,但我找不到解决方案,所以我决定在这里问一下。我需要的是使用这样的自定义键类型HashMap

HashMap<Pair<Integer, Integer>, StrategyPoint> myMap = new HashMap<Pair<Integer, Integer>, StrategyPoint> ();

但是我在这里遗漏了一些东西,因为HashMap停止正常工作。首先,Key变得不唯一,并且keySet中可以找到具有相同值的Pair的不同实例。包含键功能也不像我想的那样工作:)。

我明显错过了一些东西,我更应该以某种方式定义一种方法来比较我的Pair类中的实例。但是我尝试在我的compareTo课程中使用Pair实现Comparable,但它仍然无效。有什么建议吗?

我的原始代码有点混乱,读起来不友好,所以我举了一个例子来说明我的问题。

以下是代码:

HashMap<Pair<Integer, Integer>, StrategyPoint> myMap = new HashMap<Pair<Integer, Integer>, StrategyPoint> ();
    Pair<Integer, Integer> myPair = new Pair<Integer, Integer>(2,2);
    StrategyPoint myPoint= new StrategyPoint(2, 2, 5, 5, false);
    myMap.put(myPair, myPoint);


    Pair<Integer, Integer> searcher = new Pair<Integer, Integer> (0,0);
    searcher.setFirst(2);
    searcher.setSecond(2);
    System.out.println(myMap.containsKey(searcher));
    System.out.println(myMap.containsKey(myPair));

执行的结果是:

false

true

我已经调试了它并正在正确填充搜索器实例,但似乎HashMap拒绝在其keySet中找到它。

3 个答案:

答案 0 :(得分:14)

您必须在equals课程上正确实施hashCodePair

HashMap使用这些方法来区分和散列密钥类。

答案 1 :(得分:5)

您需要覆盖班级equals中的Pair。此方法的实现定义了Pair的两个对象如何被视为相等。

每当您覆盖equals时,您必须始终覆盖hashcode

以下是覆盖equals而不是hashcode时出错的问题(来自Effective Java,Second Ed。):

  

根据类的不同,两个不同的实例在逻辑上可能相等   equals方法,但对于Object的hashCode方法,它们只是两个   没有太多共同点的物体。因此Object的hashCode   方法返回两个看似随机的数字而不是两个相等的数字   合同要求的数字。

因为两个逻辑上相等的实例的哈希码变得不相等,如果您尝试搜索一个而另一个在集合中,则最终会查找错误的哈希桶,从而导致null

有一组rules equals的实施必须符合。另一组rules用于覆盖hashcode

答案 2 :(得分:2)

您的Pair类需要根据hashCode()的Javadoc中指定的合同实施equals()Object