hashCode在比较两个对象时会扮演什么角色?

时间:2015-04-29 16:19:56

标签: java object collision

我决定用Java学习一些主要文档。我从Object课开始,我正在研究equals方法。我知道equals正在使用hashCode方法。虽然hashCode返回int,但是可以生成有限数量的唯一哈希码。

当我尝试比较具有相同hashCode的两个不同对象时会发生什么?这甚至可以吗?

2 个答案:

答案 0 :(得分:3)

是。两个对象可以具有相同的哈希码。但是,hashcode在比较两个对象时不起作用。如果要检查类的两个对象是否为equal,请覆盖equals并定义何时应将该类的两个对象视为相等。如果要比较一个类的一个对象是否小于/大于另一个(通常在排序集合时),请实现Comparable并覆盖compareTo方法。 (您也可以实施Comparator

如果您想要将对象存储在HashSet中或将其用作HashMap中的密钥,请确保覆盖hashCode方法或您的对象/密钥将最有可能存储在不同的存储桶中导致重复。

不要忘记在您创建的课程中覆盖equals。如果你不这样做,那么对你的类对象的两个引用只有在它们引用同一个对象时才会相等。

您可以在equalshashCode文档中阅读有关equals和hashCode方法的更多信息。

答案 1 :(得分:1)

hashcode()的合同非常简单:

  • 如果两个对象根据equals方法相等,则对两个对象中的每个对象调用hashCode方法必须产生相同的整数结果。

  • 如果两个对象根据equals方法不相等,则不需要在两个对象中的每一个上调用hashCode方法必须产生不同的整数结果。

因此,任何类对象的有效散列函数都可以是:

@Override
public int hashcode() {
    return 42;
}

满足相等对象具有相同哈希码值的契约。

问题是使用上述哈希码将对象分配到存储桶(例如HashSet)的类会将所有对象分配到同一个存储桶中,从而导致严重的性能影响。最佳散列函数虽然不是严格要求,但会为不等对象生成不同的值,以便将它们分配给自己的桶。

Object.equals()的合同在进行比较时不需要使用hashcode()。但是,如果不可变对象具有昂贵的等于比较,则它可以使用哈希码值来确定是否需要进行昂贵的比较。哈希码可以在第一次计算时被缓存。因为对象是不可变的,所以哈希码不能改变,因此它可以安全地缓存在实例中。因此,哈希码可以用作等比较的优化:只需要对具有相同哈希码的实例进行昂贵的比较。

可以在Effective Java,3rd Ed中找到用于编写足够的散列函数的简单算法。 (J.布洛赫)。现代IDE还可以自动为您生成哈希函数。