【问题标题】:HashSet<POJO>.contains misbehavesHashSet<POJO>.contains 行为不端
【发布时间】:2018-08-27 23:24:56
【问题描述】:

作为 Hadoop Mapper 的一部分,我有一个 HashSet&lt;MySimpleObject&gt;,其中包含一个非常简单的类的实例,该类只有两个整数属性。应该的,我自定义了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 在构造添加到集合中的实例后永远不会更新(尽管它们有时会在代码的其他地方更新,用于同一类的其他实例);
  • 该集合可能非常大(即可以达到近 15K 条目),我想知道问题是否与此有关(例如,存储桶溢出?)。

【问题讨论】:

  • 您是否可以修改 HashSet 中已包含的对象的 i1i2 的值?
  • i1i2 的值是否会在对象插入集合后更新?
  • 请提供一个minimal reproducible example,显示contains() 在应该返回false 时返回true。就目前而言,我无法重现您的结果。
  • 你的代码中有继承吗?我不喜欢obj.getClass() != MySimpleObject.class,它不会管理子类。改用instanceof
  • @Daniel Pryden 好的,我将生成一个最小的失败示例

标签: java hadoop hashset mapper


【解决方案1】:

我敢打赌,你很难想出一个简洁的重现这个错误的方法。

您显示的代码看起来正确。我认为您的集合中的对象正在发生变异,而这一事实被其他代码掩盖了。

您可以通过临时添加来调试:

  1. boolean hashCodeCalled=false 添加到您的班级
  2. 当hashCode()被调用时,设置hashCodeCalled=true
  3. 当调用 setter 并且该布尔值为 true 时,抛出异常或记录当前堆栈跟踪

或者,您可以重构代码,使这些实例是不可变的,我敢打赌问题会消失。

【讨论】:

  • 感谢 WW,您的建议使我修复了该错误,但我仍然不确定我的实例为何/在何处发生突变。现在我确保实例化一个新的对象副本以添加到集合中,而不是相信org.hadoop.util.ReflectionUtils.newInstance(...) 确实每次都返回不同的实例,并且一切正常。我不喜欢不知道发生了什么。
猜你喜欢
  • 2012-03-16
  • 1970-01-01
  • 2015-10-06
  • 1970-01-01
  • 2013-04-14
  • 1970-01-01
  • 2011-12-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多