我的哈希表看起来像这样:
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());
其中aaa
为List<String> aaa = new ArrayList<String>()
。当然,found it
会多次打印。我做错了什么?
答案 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;
}
}