作为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()
首先用于将示例拆分为bucket和 equals()
仅为比较给定bucket中的示例而调用。
我试着改变 hasCode()
将不同的示例分散到桶中,并看到 contains()
有时仍然返回错误的结果,但不是以前失败的值。
似乎这个值也被正确地识别为超出了集合;因此,我怀疑是平等检查而不是哈希错误,但我可能是错的。。。
我在这里完全不知所措,没有主意了。有人能解释一下吗?
-----编辑-----
一些澄清: i1
& i2
对于已添加到集合中的示例,在构造之后从不更新(尽管有时在代码的其他地方,对于同一类的其他示例,它们也会更新);
集合可能相当大(即可以达到近15k个条目),我想知道问题是否与此有关(bucket overflow,例如?)。
1条答案
按热度按时间vawmfj5a1#
我敢打赌你很难想出一个简洁的复制这个错误。
显示的代码看起来正确。我认为您的集合中的对象正在发生变化,这一事实被其他代码掩盖了。
可以通过临时添加以下内容对此进行调试:
添加
boolean hashCodeCalled=false
为你们班干杯调用hashcode()时,设置
hashCodeCalled=true
当调用setter时,该布尔值true
,然后抛出异常或记录当前堆栈跟踪或者,您可以重构代码,使这些示例是不可变的,我敢打赌问题消失了。