【发布时间】:2018-08-27 23:24:56
【问题描述】:
作为 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在构造添加到集合中的实例后永远不会更新(尽管它们有时会在代码的其他地方更新,用于同一类的其他实例); - 该集合可能非常大(即可以达到近 15K 条目),我想知道问题是否与此有关(例如,存储桶溢出?)。
【问题讨论】:
-
您是否可以修改 HashSet 中已包含的对象的
i1和i2的值? -
i1和i2的值是否会在对象插入集合后更新? -
请提供一个minimal reproducible example,显示
contains()在应该返回false 时返回true。就目前而言,我无法重现您的结果。 -
你的代码中有继承吗?我不喜欢
obj.getClass() != MySimpleObject.class,它不会管理子类。改用instanceof。 -
@Daniel Pryden 好的,我将生成一个最小的失败示例
标签: java hadoop hashset mapper