作为Hadoop Mapper
的一部分,我有一个HashSet<MySimpleObject>
,其中包含一个非常简单的类的实例,该实例只有两个整数属性。我应该自定义了hashCode()
和equals()
:
public class MySimpleObject {
private int i1, i2;
public set(int i1, int i2) {
this.i1 = i1;
this.i2 = i2;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + i1;
result = prime * result + i2;
return result;
}
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (this == obj) return true;
if ( obj.getClass() != MySimpleObject.class ) return false;
MySimpleObject other = (MySimpleObject)obj;
return (this.i1 == other.i1) && (this.i2 == other.i2);
}
尽管集合实际上不包含此值,但有时以某种方式调用
mySet.contains(aSimpleObj)
会返回true
。 我了解
hashCode()
是如何首先用于将实例拆分为存储区的,而equals()
仅用于比较给定存储区中的实例的方式。我试图更改
hasCode()
中的质数,以将实例以不同的方式传播到存储桶中,结果发现contains()
有时仍返回错误的结果,但不会返回相同的先前失败值。似乎还正确地识别出该值超出了该值。因此,我怀疑相等检查而不是哈希有问题,但是我可能错了...
我在这里全神贯注,毫无主见。任何人都可以阐明这一点吗?
-----编辑-----
一些说明:
i1
和i2
在构造之后不会为添加到集合中的实例进行更新(尽管有时会在代码中的其他地方对同一类的其他实例进行更新); 最佳答案
我敢打赌,您很难拿出此bug的简要说明。
您显示的代码看起来正确。我认为您集合中的对象已发生了变异,而其他代码对您来说也很模糊。
您可以通过临时添加以下内容进行调试:
boolean hashCodeCalled=false
添加到您的类(class)hashCodeCalled=true
true
,则引发异常或记录当前堆栈跟踪或者,您可以重构代码,使这些实例不可变,并且我敢保证问题消失了。