理想的哈希码实现

时间:2013-10-18 10:06:26

标签: java eclipse equals hashcode

我的课程如下

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. 使用所有三个名称,年龄和身份。
  3. 两者的优点和缺点是什么?

4 个答案:

答案 0 :(得分: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;
}

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

答案 1 :(得分:0)

如果不考虑太多,我会使用:apache' s 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()进行比较是否一致?如果,为什么我应该使用三个属性而不是两个

Check this Hashing it out Article,有点旧但很好的细节。

答案 2 :(得分:0)

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

此外,如果您的ID是唯一的,我们将为不同的对象提供不同的哈希码,以便它们有效。

答案 3 :(得分:0)

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

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

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

相关问题