在java中以有效的方式实现pojo的哈希码

时间:2015-05-14 15:49:50

标签: java hashcode

在一次采访中,有人要求我以有效的方式显示hashcode和equals方法的实现,所以我构建了下面的pojo但是访谈者说这不是正确的,也是最好的实现,因为它可能导致一个碰撞,请问请问下面哈希码的执行是否正确

public class Emp  {

    String name, job;
    int salary;

    public Emp(String n, String j, int s) {
        this.name = n;
        this.job = j;
        this.salary = s;

    }

    public int hashcode() {
        return name.hashCode() + job.hashCode() + salary;
    }

    public boolean equals(Object o) {

        Emp e1 = (Emp) o;
        return this.name.equals(e1.name) && this.job.equals(e1.job) && this.salary == e1.salary;
    }
    }

2 个答案:

答案 0 :(得分:2)

您正在使用:

  • 两个String#hashCode调用,其算法有争议 - 请参阅here了解有趣的帖子
  • 您正在为最后部分添加薪水(int !!)
  • 最后也是最重要的是,使用种子:将每个字段乘以素数并将结果相加

您可以查看IDE如何自动生成哈希码以获得更好的主意。

在Eclipse中:

  • 右键点击来源(或alt - shift - S
  • Source
  • Generate 'hashCode()' and 'equals()'...

答案 1 :(得分:1)

只是将hashCode加起来并不是一个好主意。那里有图书馆(例如Project Lombok)为你做这件事。或者您可以简单地请求您的IDE生成一个或者您。对于例如Eclipse has an option根据您班级中的字段生成hashCode

推断一下;我们假设您有以下hashCode s:

name.hashCode() = 200
job.hashCode()  = 400
salary          = 1000000

但是你可能有另一个独特的员工,最终得到以下hashCode

name.hashCode() = 400
job.hashCode()  = 200
salary          = 1000000

正如您所看到的,即使我们在这里有两名不同的员工,但我们最终都会使用相同的hashCodehashCode的理想属性是确保您正在散列的实体最终得到尽可能均匀的分布。

如果查看所有“好”hashCode实现,您会注意到与素数相乘。这可以确保即使所有单个hashCode的总和相同,您仍然会有一个不同的整体hashCode。你可以用上面的例子来试试。