【问题标题】:Using intermediate array for hashCode and equals对 hashCode 和 equals 使用中间数组
【发布时间】:2013-11-02 14:35:25
【问题描述】:

由于我经常在两个地方处理类的结构变化很痛苦:

class A {
  class C{}
  class B{}
  private B bChild;
  private C cChild;

  private Object[] structure() {
    return new Object[]{bChild, cChild};
  }

  public int hashCode() {
      Arrays.hashCode(structure());
  }

  public boolean equals(Object that) {
    //type check here
    return Arrays.equals(this.structure(), ((A)that).structure());
  }
}

除了对原语进行装箱外,这种方法还有什么不好的? 可以改进吗?

【问题讨论】:

  • 除了它不能编译之外,你的意思是?到目前为止,它没有什么可推荐的。
  • 这种方法试图解决什么问题?
  • @Vitaliy,将对象结构封装在两个地方而不是三个地方(字段、等于、hashCode)。
  • 你使用的是什么 JDK? (是 1.7 吗?)
  • 我使用的是 1.6 和 1.7。考虑迁移到 1.7。

标签: java arrays hash equals


【解决方案1】:

这是一种重用库方法的聪明方法,这通常是个好主意;但它会进行大量的过度分配和数组操作,这在这些常用方法中可能非常低效。总而言之,我会说它很可爱,但它不会通过评论。

【讨论】:

  • 我们能解决这些问题吗?例如通过重用数组实例?
  • 这会增加每个对象的内存使用量。更糟糕的是!
  • stackoverflow.com/a/27609/125562 - 高度投票的答案也为此目的使用了帮助对象。
【解决方案2】:

在 JDK 7 中,他们添加了 java.util.Objects 类。它实际上以一种提醒您所写内容的方式实现了哈希和等于实用程序。关键是这种方法实际上得到了 JDK 开发人员的认可。 Ernest Friedman-Hill 是有道理的,但在大多数情况下,我认为不值得以牺牲可读性为代价节省额外的几条机器指令。

例如:hash实用方法实现为:

public static int hash(Object... values) {
    return Arrays.hashCode(values);
}

【讨论】:

    【解决方案3】:

    熟悉代码的人会更难看到发生了什么。正如我之前错误的答案所证明的那样,它比列出各个字段不那么“明显”。确实,“等于”通常是通过传入的“对象”实现的,因此值得商榷,但输入是在引用相等检查之后强制转换的。这里不是这样。

    一个改进可能是将数组存储为私有数据成员,而不是使用结构方法创建它,牺牲一点内存以避免装箱。

    【讨论】:

    • 这是 Java,不是 C++
    • 我不做 C++。当我说比较内存位置是否相等时,我的意思是您正在比较对象是否是内存中的相同实例......占用相同的空间,因为它是相同的东西。
    • -1 你在这里试图表述的似乎是关于引用相等。不,在我的课堂上从未检查过引用相等性。
    • 静态 arrays.equals 方法检查对象数组中的各个元素,但它仍然是同质对象数组,而不是 B 和 C 的数组。但是,我确实忘记了多态性, 这将适用于此。哎呀。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-08
    • 2019-06-02
    • 1970-01-01
    相关资源
    最近更新 更多