作为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()有时仍返回错误的结果,但不会返回相同的先前失败值。
似乎还正确地识别出该值超出了该值。因此,我怀疑相等检查而不是哈希有问题,但是我可能错了...

我在这里全神贯注,毫无主见。任何人都可以阐明这一点吗?

-----编辑-----
一些说明:
  • i1i2在构造之后不会为添加到集合中的实例进行更新(尽管有时会在代码中的其他地方对同一类的其他实例进行更新);
  • 集合可能很大(即可以达到近15,000个条目),我想知道问题是否可以与此关联(例如,存储桶溢出?)。
  • 最佳答案

    我敢打赌,您很难拿出此bug的简要说明。

    您显示的代码看起来正确。我认为您集合中的对象已发生了变异,而其他代码对您来说也很模糊。

    您可以通过临时添加以下内容进行调试:

  • boolean hashCodeCalled=false添加到您的类(class)
  • 调用hashCode()时,设置hashCodeCalled=true
  • 调用setter时,该 bool(boolean) 值为true,则引发异常或记录当前堆栈跟踪

  • 或者,您可以重构代码,使这些实例不可变,并且我敢保证问题消失了。

    10-05 17:58
    查看更多