Java:重写equals方法在查找哈希表的键时不起作用?

时间:2011-05-17 13:59:06

标签: java

我的哈希表看起来像这样:

Hashtable<Mapping, Integer> mappingCount = new Hashtable<Mapping, Integer>();

我想使用此代码:

if (mappingCount.get(currentMapping) != null)
    mappingCount.put(currentMapping, mappingCount.get(currentMapping) + 1);
else
    mappingCount.put(currentMapping, 1);

为了能够从散列表中获取值,对于类Mapping,我执行了以下操作:

@Override
public boolean equals(Object obj) {
    return ((Mapping)obj).mappingXML.equals(this.mappingXML);
}

然而,由于mappingCount.get(currentMapping)始终会导致null,因此无法解决问题。为了确保没有错,我做了以下几点:

if (aaa.contains(currentMapping.getMappingXML()))
    System.out.println("found it!");
else
    aaa.add(currentMapping.getMappingXML());

其中aaaList<String> aaa = new ArrayList<String>()。当然,found it会多次打印。我做错了什么?

5 个答案:

答案 0 :(得分:9)

您还需要覆盖hashCode()方法。

来自JavaDocs

  

成功存储和检索   来自哈希表的对象,即对象   用作密钥必须实现   hashCode方法和equals方法。

原因是Hashtable使用hashCode作为初步测试来查看两个对象是否等于。如果hashCode匹配,则它使用equals来检查是否发生了冲突。

hashCode()的默认实现返回对象的内存地址,对于两个相等的对象,它们的哈希码也必须相等。

另请参阅hashCode()的一般合约。

答案 1 :(得分:5)

正确覆盖equals和hash代码的所有建议都是正确的; Joshua Bloch告诉您如何正确地做到这一点。

但同样重要的要求是地图中的键必须是不可变的。如果您的类可以更改其值,则在将其添加到地图后,equals和hash代码可能会更改;灾难发生了。

答案 2 :(得分:4)

每当您覆盖equals时,必须覆盖hashCode

答案 3 :(得分:2)

您还需要覆盖hashCode

来自Object#hashCode doc:

  

返回。的哈希码值   宾语。支持此方法   哈希表的好处,如   java.util.Hashtable。

提供的那些      

hashCode的一般合约是:

     
      
  • 每当在同一个对象上多次调用它时   执行Java应用程序,   hashCode方法必须一致   返回相同的整数,提供否   用于等比较的信息   对象被修改。这个   整数不需要保持一致   从一个应用程序的执行   到另一个执行相同的   应用
  •   
  • 如果两个对象根据equals(Object)方法相等,那么   在每个上调用hashCode方法   两个对象必须产生相同的   整数结果。
  •   
  • 如果两个物体不相等,则不需要   等于(java.lang.Object)方法,然后   在每个上调用hashCode方法   两个对象必须产生不同的   整数结果。然而   程序员应该意识到这一点   产生不同的整数结果   不平等的物体可能会改善   哈希表的表现。
  •   
     

尽可能合理,   class定义的hashCode方法   对象确实返回不同的整数   对于不同的对象。 (这是   通常通过转换实现   对象的内部地址   变成一个整数,但是这个   实施技术不是   JavaTM编程所要求的   语言。)

答案 4 :(得分:1)

您还必须实施hashcode()

示例:

public class Employee{
    int        employeeId;
    String     name;
    Department dept;

    // other methods would be in here 

    @Override
    public int hashCode() {
        int hash = 1;
        hash = hash * 17 + employeeId;
        hash = hash * 31 + name.hashCode();
        hash = hash * 13 + (dept == null ? 0 : dept.hashCode());
        return hash;
    }
}