我可以将班级成员的哈希码用于班级吗?

Posted

技术标签:

【中文标题】我可以将班级成员的哈希码用于班级吗?【英文标题】:Can I use hashcode of class member for class? 【发布时间】:2014-09-19 15:03:06 【问题描述】:

我有一个最终字符串作为唯一 ID 的课程。当然我想覆盖equals所以比较只基于ID。像下面这样只返回 ID 的哈希码是正确的做法吗?

class ItemSpec
    final String name;

    ...

    @Override
    public boolean equals(Object o)
        if(o != null && o instanceof ItemSpec)
            return name.equalsIgnoreCase(((ItemSpec)o).name);
         else
            return false;
        
    

    @Override
    public int hashCode()
         if(name == null)
             return 0;
          else
             return name.hashCode();
         
    

【问题讨论】:

请注意,您的 equals 方法假定 name 不为空,但您的 hashCode 方法假定它可能为空。是哪个? @JonSkeet 抱歉,我在添加后注意到了这一点。已编辑。 看不到编辑。在 equals 中仍然不能为空。 【参考方案1】:

如果您的 equals 不区分大小写,则不会。您可以有两个 ItemSpec 相同但具有不同的哈希码。这打破了哈希码最关键的要求。

您的equals 必须同意您的hashCode。因此,如果您要不区分大小写地比较它们,则必须不区分大小写地编写 hashCode

@Override
public int hashCode()
     if (name == null)
         return 0;
      else
         return name.toLowerCase().hashCode();
     

您的hashCode 方法也暗示name 可以为空。如果是这样,您也应该在您的 equals 方法中对其进行空检查。

【讨论】:

不会有a.equalsIgnoreCase(b)a.toLowerCase().equals(b.toLowerCase()) 为假的情况吗? 很好,但想指出与 assylias 相同的情况:转换可能会为特定于语言环境和 unicode 相关的麻烦打开大门...... 嗯,我意识到自己和编辑,但你先生对我来说太快了;) 如果存在equalsIgnoreCasetoLowerCase 更粗糙的情况,那么我想确定它们匹配的最好方法是在equals 方法中使用a.toLowerCase().equals(b.toLowerCase())【参考方案2】:

我认为你的方法没有任何问题。

但是,我经常看到以下实现:

public int hashCode() 
    final int prime = 31;
    int result = super.hashCode();
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    return result;

更新: 这是一个有更好解释的链接: Best implementation for hashCode method

【讨论】:

这看起来像是自动生成的代码,除了增加计算时间之外并没有什么作用...... 如果您的 equals 方法中不需要 super.equals,则不能将 super.hashCode 合并到您的哈希码中。否则两个相等的对象可能会得到不同的哈希码。 我从我的项目中获取了这段代码。我不是 100% 确定,如果我是手动完成的,或者它是 Eclipse 生成的。但我确实看过实现 hashCode 的最常见方法,在我看来这是最常见的方法。 它在 Joshua Bloch 的《Effective Java》一书中得到普及。它有多种变体,并且很多 JDK 库都使用它。例如 Arrays.hashCode。这样做是为了在有限范围内散布散列码,并尝试减少散列范围内的池化/热点。这都会影响哈希图等的性能。

以上是关于我可以将班级成员的哈希码用于班级吗?的主要内容,如果未能解决你的问题,请参考以下文章

测试随笔

哪个哈希码哈希映射实现用于值检索

还记得鼠标点击的地方吗?数组列表?哈希码?

是否始终将 UUID 用于 JPA 实体的 id 属性并在其上使用等于和哈希码?

如何将哈希码对象值转换为字符串变量

哈希表哈希避免负哈希码