【问题标题】:Creating .hashcode() and .equals() methods for a large object为大对象创建 .hashcode() 和 .equals() 方法
【发布时间】:2014-12-10 03:48:11
【问题描述】:

我的课程有很多(大约 100 个)字段。我想为这些字段实现hashCode()equals() 方法,有没有其他方法可以手动执行?

【问题讨论】:

  • 100 是单个类的疯狂数量的字段...考虑重构。
  • eclipse 可以自动为你生成这些方法
  • 你应该先重写你的类。我想不出除了上帝之外的任何实体都有自己的 100 个属性 ;-)
  • 我也不喜欢日食或垃圾邮件领域,只是指出如果 OP 不知道。
  • 你的 100 个字段是什么?它们都是同一类型吗?

标签: java equals hashcode


【解决方案1】:

没有很好的答案。这里有一些建议。正如其他人评论的那样,100 个字段太多了。你最好的办法是重构类。但是,如果你必须把它们放在一起:

  • 您能否使用地图(或其他集合)来保存许多字段?

如果是这样,您可以使用它们内置的 hashCode() 和 equals() 方法。 (或@dimo414 指出的番石榴等)

  • hashcode() 应该只考虑不可变字段(或至少很少改变的字段。)

如果只有少数字段是不可变的,那将大大简化您的 hashCode() 代码。而且,更重要的是,让它正确。 :-)

  • 如果有 100 多个字段,两个实例永远相等的现实机会是多少?

如果答案是“极少”,请问自己是否可以使用基本的对象相等(实际上是使用 ==)?

  • 您是否已经有一个信息丰富的 toString() 方法?

如果是这样,您可以有时将该字符串用作低效但易于编码的 hashCode() 和 equals()。例如:

public int hashCode() { return this.toString().hashCode(); }

public boolean equals(Object o) {
   return (o instanceof MyClass) &&
          (this.toString().equals(o.toString()));
}

【讨论】:

  • 如果修改一个对象改变了它可以比较的其他对象的集合,那么这种修改影响hashCode()值是可以的。通常,对象将对某事物的引用存储到地图中然后——当地图仍然持有该引用时,以这样的方式对其进行修改以使其与之前没有的事物比较相等,或者反之亦然。尽管如果代码知道地图永远不会看到两个对象比较相等,那么代码可以修改存储在地图中的对象而不会违反上述限制...
  • ...在某个时间和在其他时间不相等,并且在哈希码保持不变的情况下更改哈希码会破坏地图,大多数代码使用正确的映射不应该关心影响相等性的更改是否也会影响哈希码。
【解决方案2】:

其他人指出,这么大的对象可能不是一个很好的模式,所以我假设你已经知道了,并且已经决定继续。我还将假设这个对象(大部分)是不可变的,因为为可变对象实现.hashCode() 通常是一个糟糕的计划(至少,你必须小心将可变对象放在HashSet 或作为键入HashMap)。

如果您有一个包含大量字段的类,您可以通过利用执行相同操作的现有功能来避免定义复杂的.hashCode().equals().toString() 方法。一个简单的选择是为您的字段构造一个ListMap,然后简单地调用该Collection 的相应方法。如果需要,您甚至可以缓存这些函数的返回值,而不是保留整个 Collection

还有许多有用的实用程序可以使这些方法更容易;太多了,无法一一列举,但我会尝试列举几个特别有用的:

此外,您可以在运行时在您的对象中use reflection to get all the fields。这将比硬编码实现慢,但编写起来可能会更快。如果您不太在意速度,这是一个不错的选择。

【讨论】:

    【解决方案3】:

    我认为最好使用 eclipse 功能hashCode()equals() 生成代码,这对于实现这些方法非常有用。

    【讨论】:

    • 在所有 100 多个字段上生成哈希码几乎肯定是错误的,因为许多字段都是可变的。我想你可以使用 Eclipse 启动,然后删除其中的许多。
    • @user949300 是的,eclipse 会很容易地创建代码,然后我们会很容易地操作它。
    【解决方案4】:

    虽然拥有具有这么多字段的对象并不是一个好习惯,但有时旧约束会使您陷入糟糕的境地。

    无论大小如何,我发现覆盖这些方法的最简单方法是使用 Apache 公共库。它使用反射从实例中生成值,并且有多种方法可以配置结果。如果字段更新,我也不必记住重新生成方法,这与 eclipse 生成的方法不同。

    @Override
    public final boolean equals(final Object obj) {
        if (obj == this) {
            return true;
        }
    
        if(obj != null && obj.getClass() == this.getClass()) {
            return EqualsBuilder.relectionEquals(this, obj, true);
        }
    
        return false;
    }
    
    @Override
    public final int hashCode() {
        return HashCodeBuilder.relectionHashCode(this);
    }
    
    @Override
    public final String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
    }
    

    【讨论】:

      猜你喜欢
      • 2011-08-08
      • 2013-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多