2

至于Person的定义:

public class Person {
    private int id;
    private int characteristics;
    public boolean equals (Object obj) {
           if (obj == this) {
                 return true;
           }
           if (obj instanceof Person) {
                 if (id == ((Person) obj).id) {
                     return true;
                 } else if (characteristics == ((Person) obj).characteristics) {
                     return true;
                 }
           }
           return false;
    }
}

导致2个Person对象a并且如果返回b必须具有相同的哈希码,我应该如何实现该方法?a.equals(b)truehashCode

解决方案

equals根据Java的等价协议,我的方法实现不正确:传递性不满足:a.id = 1, a.characteristic = 2, b.id = 1, b.characteristic = 3, c.id = 2, c.characteristic = 3; a.equals(b) == true, b.equals(c) == true, 但是a.equals(c) == false

4

3 回答 3

5

由于您的类在它们各自的idcharacteristics字段相等时认为对象相等,因此您可以在此处合理使用的唯一哈希码是所有实例的常量值:

public int hashCode() {
    return 0;
}

这将使基于哈希的查找执行得非常糟糕。

非此即彼的测试equals()通常是一个坏主意。对象实际上并不相等,是吗?也许他们只是“彼此的匹配”?也许您应该考虑不理会equals()并实施其他一些比较方法。


正如 Thomasz 指出的那样,您的equals()测试不是传递性的。如果a.equals(b) && b.equals(c)是真的那么a.equals(c)一定是真的。这不适用于您的重载,因此您的实现违反了equals(). 我强烈敦促您以不同的方法实施此测试,不要equals()理会。

于 2012-06-11T20:56:18.033 回答
1

这是为您的班级自动生成的内容:

@Override
public int hashCode() {
    int result = id;
    result = 31 * result + characteristics;
    return result;
}

经过几次重构:

@Override
public int hashCode() {
    return 31 * id + characteristics;
}

为了记录,只有我还是你equals()坏了?id如果s 或相等,则您认为两个对象相等characteristics,但不一定两者都相等。这意味着您的相等性不是传递性的,一旦您的对象进入荒野,这可能会产生真正意想不到的副作用。

这是一个不错的实现:

@Override
public boolean equals(Object o) {
    if (this == o) {
        return true;
    }
    if (!(o instanceof Person)) {
        return false;
    }

    Person person = (Person) o;
    return characteristics == person.characteristics && id == person.id;
}
于 2012-06-11T20:40:16.260 回答
0

如果具有相同id意味着始终具有相同characteristics(这似乎是您equals()有效的必要条件),那么您的哈希码可以characteristics单独使用:

@Override
public int hashCode() {
    return characteristics;
}

如果不是这种情况,您可能需要重新考虑使用 Java 相等性来表达这种关系,正如@cdhowie 所建议的那样。

于 2012-06-11T21:00:25.813 回答