【问题标题】:Overriding HashCode覆盖哈希码
【发布时间】:2014-02-17 17:55:00
【问题描述】:

我有一个类,它是一个 Set,我重写 .equals() 以检查集合是否在元素方面相等。我如何覆盖 HashCode,因为据我所知,两者之间存在一些相互依赖

public class ASet{
Set g=new Set();


public boolean equals(Object s1)
{
    Set S= (Set)s1;
    for(Object o : S.getcontents())
    {
        for(Object r : g.getcontents())
        {
            if(!o.equals(r))
            {
                return false;
            }
        }
    }
    return true;
}

 public int hashCode() {
       ?????????
 }

【问题讨论】:

  • 除非您想将此 Set 放入另一个 HasSet 或 HashMap 中,否则您不需要覆盖 hashCode。
  • 为什么要包装 Set ?
  • 顺便说一句,我认为您的等号不正确。如果任一集合包含超过 1 个元素,它将始终返回 false。
  • @TwilightSun:无论何时你覆盖equals(),你都应该覆盖hashCode()
  • 忽略其他评论者提出的实现问题,在the javadocs for Object中明确定义了hashCode的实现规则。在这种情况下,如果两个 ASet 具有相同的 getcontents,那么它们应该返回相同的 hashCode()。由于您不太可能拥有一组哈希 ASet(因为您不会再次使用此代码),因此只需 return 1; 并且您的 hashCode() 将是有效的。

标签: java equals hashset


【解决方案1】:

首先,让我们修复您的 equals 实现,因为它不正确:您的代码不是成对比较元素的相等性,而是检查第一个集合的每个元素与第二个集合的每个元素。因此,在此方案下,两个集合被视为相等的唯一情况是两个集合都包含一个元素,并且它们包含的元素相同。

您应该创建两个迭代器,并将它们循环在一起在一个循环中。现在您可以将第一个迭代器返回的元素与第二个迭代器返回的元素进行比较,如果不相同则返回false

现在让我们做哈希码:理论上,您可以简单地将元素的各个哈希码相加,这将是hashCode() 的有效实现:

public int hashCode() {
    int res = 0;
    for(Object r : g.getcontents()) {
        res += r.hashCode();
    }
    return res;
}

但是,这不是您可以制作的最佳哈希码,因为具有不同排序的两个集合将具有相同的哈希码。更好的方法是在添加下一个哈希码之前将前一个值乘以一个素数(31 是一个常见的例子),如下所示:

public int hashCode() {
    int res = 0;
    for(Object r : g.getcontents()) {
        res = 31 * res + r.hashCode();
    }
    return res;
}

最后,关于集合及其哈希码的一点说明:覆盖哈希码的主要目的是让您可以将对象用作基于哈希的集合(哈希集或哈希映射)中的键。但是,在使用可变对象(例如集合和列表)作为映射或集合中的键时,您应该非常小心,因为改变已经放入容器中的键会危及基于散列的容器的结构完整性。

【讨论】:

  • 他实际上并没有实现Set,他只是把它包装起来,为什么他需要重写equals()
  • 如果我使用像 TreeSet 这样的 Set 实现的默认 .equals(),如果我有 2 个不同的 ASet 实例,它们包含对象(具有相同的字段值)作为元素呢?在比较它们的元素时,它们会被认为是平等的吗?
  • @JigarJoshi 人们可能想要这样做的唯一原因是作为一种练习。也许计划是在Set 之外添加更多成员,或者实现他自己的集合。
  • @user3236409 此实现要求具有相同的元素,并且还以相同的顺序枚举这些元素。如果你想让它不区分顺序,你可能需要使用一个额外的集合对象。但是,这会使您的 equals 方法变得非常昂贵 - 比您希望的 equals 方法要贵得多。
  • 完全相同是什么意思?喜欢相同的实例?。我的意思是,如果我比较 TreeSet 的元素明智元素,这些元素是对象但不同的实例,但所有字段值在代码方面都相同且相同。
猜你喜欢
  • 1970-01-01
  • 2019-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多