我们如何决定集合的hashCode()方法的最佳实现(假设equals方法已被正确重写)?


当前回答

我更喜欢使用实用工具方法从谷歌集合库从类对象,帮助我保持我的代码干净。equals和hashcode方法通常都是从IDE的模板中创建的,所以它们的可读性不太好。

其他回答

只是一个快速的注释,以完成其他更详细的答案(在代码方面):

如果我考虑如何在java中创建哈希表的问题,特别是jGuru FAQ条目,我相信可以判断哈希代码的其他标准是:

同步(算法是否支持并发访问)? 失败安全迭代(算法是否检测到迭代过程中发生变化的集合) 空值(哈希码是否支持集合中的空值)

如果我正确理解你的问题,你有一个自定义的集合类(即一个从集合接口扩展的新类),你想实现hashCode()方法。

如果您的集合类扩展了AbstractList,那么您就不必担心它,因为已经有equals()和hashCode()的实现,它通过遍历所有对象并将它们的hashCodes()相加来工作。

   public int hashCode() {
      int hashCode = 1;
      Iterator i = iterator();
      while (i.hasNext()) {
        Object obj = i.next();
        hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
      }
  return hashCode;
   }

现在,如果你想要的是计算特定类哈希码的最佳方法,我通常使用^(按位排他或)操作符来处理我在equals方法中使用的所有字段:

public int hashCode(){
   return intMember ^ (stringField != null ? stringField.hashCode() : 0);
}

对于简单类,通常最容易基于equals()实现检查的类字段实现hashCode()。

public class Zam {
    private String foo;
    private String bar;
    private String somethingElse;

    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        if (obj == null) {
            return false;
        }

        if (getClass() != obj.getClass()) {
            return false;
        }

        Zam otherObj = (Zam)obj;

        if ((getFoo() == null && otherObj.getFoo() == null) || (getFoo() != null && getFoo().equals(otherObj.getFoo()))) {
            if ((getBar() == null && otherObj. getBar() == null) || (getBar() != null && getBar().equals(otherObj. getBar()))) {
                return true;
            }
        }

        return false;
    }

    public int hashCode() {
        return (getFoo() + getBar()).hashCode();
    }

    public String getFoo() {
        return foo;
    }

    public String getBar() {
        return bar;
    }
}

最重要的是保持hashCode()和equals()的一致性:如果equals()对于两个对象返回true,那么hashCode()应该返回相同的值。如果equals()返回false,那么hashCode()应该返回不同的值。

使用Apache Commons EqualsBuilder和HashCodeBuilder上的反射方法。

首先确保equals被正确实现。摘自一篇IBM DeveloperWorks文章:

对称性:对于两个参考,a和b,当且仅当b等于(a)时,a等于(b) 自反性:对于所有非空引用,a.equals(a) 及物性:如果a等于(b) b等于(c),那么a等于(c)

然后确保它们与hashCode的关系尊重联系人(来自同一篇文章):

与hashCode()的一致性:两个相等的对象必须具有相同的hashCode()值

最后,一个好的哈希函数应该努力接近理想的哈希函数。