有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用哈希代码确定对象等价性

假设我有一个简单的类,它代表一个游戏块,名为^{

public class Tile {

    public final int x;
    public final int y;
    public final int plane;

    public Tile(int x, int y, int plane) {
        this.x = x;
        this.y = y;
        this.plane = plane;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        } else if (obj instanceof Tile) {
            Tile other = (Tile) obj;
            return other.x == x && other.y == y && other.plane == plane;
        }
        return false;
    }

    @Override
    public int hashCode() {
        return Objects.hash(x, y, plane);
    }
}

作为一个负责任的公民,我实现了hashCode方法,以确保根据equals的合同,等价对象的哈希代码是相等的。然后我在想,对于任何两个Tile对象,如果它们的xyplane字段的值相同,那么哈希代码应该是相等的。那么,为什么不直接使用来检查对象是否等效,而不是单独比较字段的值呢

更明确地说,为什么不替换:

@Override
public boolean equals(Object obj) {
    if (obj == this) {
        return true;
    } else if (obj instanceof Tile) {
        Tile other = (Tile) obj;
        return other.x == x && other.y == y && other.plane == plane;
    }
    return false;
}

简单地说:

@Override
public boolean equals(Object obj) {
    return obj == this || obj != null && obj.hashCode() == hashCode();
}

我的一部分感觉这是一种糟糕的做法。这感觉就像是循环推理。然而,我想不出一个有效的、实际的理由来解释为什么这是一种糟糕的做法

简而言之:使用hashCode的结果来确定equals的结果是否合适


共 (2) 个答案

  1. # 1 楼答案

    不。可以这样想:对于三个int的每个组合,有2^32*2^32*2^32=2^96个不同的可能Tile

    只有2^32个可能的hashCode

    因此,对于任何给定的Tile,将有2^64不同的可能的Tile具有相同的哈希代码

    简而言之:散列码不是唯一的许多对象将碰巧具有相同的哈希代码,即使它们不相等

    (通常,请记住return 0;hashCode()的有效实现。)

  2. # 2 楼答案

    ^{}合同:

    It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results.

    两个“相等”的对象应该具有相同的哈希代码

    两个“不等”对象可以具有相同的哈希代码