【问题标题】:Is this a good implementation of hashCode()?这是 hashCode() 的一个很好的实现吗?
【发布时间】:2015-06-11 19:17:27
【问题描述】:

我有一个class,将在HashSet 中使用。它只包含两个成员,并且都是相同类型的接口。这是它的样子:

class MyClass{
    MyInterface a;
    MyInterface b;

    public int hashCode(){
         return a.hashCode() + b.hashCode();
    }

    public boolean equals(Object obj){
         if(!(obj instanceof MyClass)
              return false;
         MyClass other (MyClass) obj;
         return (this.a == other.a && this.b == other.b) || (this.a == other.b && this.b == other.a);
    }
}

如您所见,如果两个 MyClass 实例包含相同的两个 MyInterface 实例,则它们是“相等的”。

现在,我在想,对于hashCode(),我可以将其成员的默认哈希码相加。这够好吗?如果不是,对于这种情况,hashCode() 的正确实现是什么?

【问题讨论】:

  • a和b的hashcode是怎么定义的?
  • 这将提供不相等的哈希码分布:Integer.MaxValue / 2 周围的元素与极端元素相比将不成比例地表示,从而导致更多的哈希冲突。
  • 你也可以使用:return Objects.hash(a, b);
  • @assylias 不,这将为相等的对象提供两个不同的哈希码,因为 [a, b] 等于 [b, a]
  • @assylias OP 似乎需要一些与订单无关的东西,Objects.hash 不是

标签: java equals implementation hashcode


【解决方案1】:

是的,这很好。相当于对二元素集实现Set.hashCode()

【讨论】:

  • @River:就像我在其他地方评论的那样,假设 a.hashCode()b.hashCode() 有适当的哈希码实现,一开始就提供适当的价值分配,我真的不明白额外的计算会有什么帮助减少碰撞的可能性。 OP的实现很好。
  • 话虽如此,您几乎可以肯定使用微调的哈希函数做得更好(更少的冲突)。真正的问题是,是否值得您花时间优化此功能,而不是简单地坚持使用“足够好”的功能。
【解决方案2】:

我会说不。这是否意味着MyClass 的这两个实例将哈希到相同的值:

MyClass {
  a.hashCode = 2;
  b.hashCode = 3;
}

MyClass {
  a.hashCode = 1;
  b.hashCode = 4;
}

【讨论】:

  • 所以你有一个哈希冲突。所以呢?你有更好的建议吗?
  • 这一定会发生......完美的哈希函数几乎是不可能的
  • 也许我的例子过于简单,但似乎更完整的实现可以最大限度地减少碰撞次数。我有更好的建议吗?没有。
  • 您可以组合 + 和 *,它们既是关联的又是可交换的(这是必需的):(a.hashCode() + b.hashCode()) * 31 + (a.hashCode() * b.hashCode())
  • @Clashsoft:假设 a.hashCode()b.hashCode() 具有适当的哈希码实现,一开始就提供适当的价值分配,我认为没有任何令人信服的理由使计算复杂化。
【解决方案3】:

是的。

因为即使有 hashCode 冲突,the docs state:

如果两个对象不相等,则不需要 equals(java.lang.Object) 方法,然后调用 hashCode 方法 这两个对象中的每一个都必须产生不同的整数结果。

【讨论】:

    猜你喜欢
    • 2015-01-04
    • 1970-01-01
    • 1970-01-01
    • 2013-11-11
    • 1970-01-01
    • 2014-09-23
    • 2015-05-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多