2

我有以下课程

public class Hash {
    int age;
    int id;
    String name;
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + id;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Hash other = (Hash) obj;
        if (id != other.id)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }


}

在这我只使用了两个属性 name 和 id 来生成 .equals 方法,但现在我的问题是。什么应该是实现 .hashCode() 方法的好方法。

  1. 仅使用名称和 ID
  2. 使用所有三个姓名、年龄和身份证。

两者的优点和缺点是什么?

4

4 回答 4

3

计算哈希码的一个重要规则是您只能使用与equals()实现相关的信息。

由于您不在您的方法中使用,因此age在您的equals方法中使用它是错误的hashCode!推理很简单:

  • 想象两个对象 o1 和 o2,其属性为“id=1,age=2,name=foo”和“id=1,age=3,name=foo”。
  • 调用equals()会返回true
  • 但是,调用hashCode()(在使用 的实现上age)将返回两个不同的值!

这并不意味着必须使用所有此类信息。有时只使用一个子集有好处(例如,如果有一些大的、难以散列的对象不太可能是两个对象之间的唯一区别)。

对您来说最原始、最正确的实现是:

public int hashCode() {
    return 0;
}

这将是正确的,但效率非常低(因为每个对象都会散列到相同的值,显然!)。

于 2013-10-18T10:15:34.710 回答
0

不用想太多我会使用:apache的HashCodeBuilder

要使用这个类,编写代码如下:

 public class Person {
   String name;
   int age;
   boolean smoker;
   ...

   public int hashCode() {
     // you pick a hard-coded, randomly chosen, non-zero, odd number
     // ideally different for each class
     return new HashCodeBuilder(17, 37).
       append(name).
       append(age).
       append(smoker).
       toHashCode();
   }
 }

有一个答案:是否唯一nameid唯一地标识该类的每个对象并且与比较一致equal()?如果,那我为什么要使用三个属性而不是两个

查看这篇Hashing it out文章,有点旧但细节很好。

于 2013-10-18T10:13:18.167 回答
0

如果您的 id 是唯一的,我认为您应该只使用 id 字段来生成哈希码。通过这种方式,您将能够通过仅使用 id 创建对象来从集合中搜索您的对象。

此外,如果您的 id 是唯一的,我们将为不同的对象使用不同的哈希码,因此它会很有效。

于 2013-10-18T10:16:31.590 回答
0

哈希码方法的实现取决于您希望如何完成分桶-

  1. 可以选择将所有偶数 id 的对象放在一个桶中,将奇数 id 的对象放在另一个桶中。
    @Override
    public int hashCode() {
       return this.id % 2 == 0 ? 1 : 2;
    }
  1. 或者您可以选择将年龄在 0-10 岁的人放在一个桶中,将 10-20 岁的人放在另一个桶中,依此类推。
    @Override
    public int hashCode() {
       return this.age / 10 ;
    }

关键是,这实际上取决于您的对象在范围内的分布方式(如果对象在桶中正确划分,您将获得更好的性能)以及您希望如何进行分桶。

于 2013-10-18T10:28:07.553 回答