繁体   English   中英

为什么equals中使用的所有字段也应该用在哈希码中?

[英]Why all fields used in equals should be also used in hashcode?

@Edit:我正在使用这个库http://jqno.nl/equalsverifier/检查是否正确写入了equalshashCode

假设我们有这个课程:

final class Why {
    private final int id;
    private final String name;

    Why(final int id, final String name) {
        this.id = id;
        this.name = name;
    }

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

        final Why why = (Why) o;

        if (id != why.id) return false;
        return name != null ? name.equals(why.name) : why.name == null;
    }

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

hashCode我只在id字段上转发,因为这会给我很好的,非碰撞的哈希值。 值得注意的是,这种hash方法符合equals-hashCode所有规则。 我不想做一些总结哈希的花哨技巧,即:

@Override
public int hashCode() {
    int result = id;
    result = 31 * result + (name != null ? name.hashCode() : 0);
    return result;
}

所以你能解释一下为什么EqualsVerifer默认需要使用hashCode方法中equals方法的所有字段吗?

java.lang.AssertionError: Significant fields: equals relies on subValue, but hashCode does not.

免责声明:我是EqualsVerifier的创建者。

它是默认行为的原因是因为它通常是一种很好的做法,EqualsVerifier希望鼓励其用户遵循良好做法。 您希望hashCode分布尽可能大,以确保在使用基于散列的集合时具有良好的性能。

如果您有充分的理由做其他事情(从您的问题判断,看起来您可能有),您可以通过添加.suppress(Warning.STRICT_HASHCODE)来禁用此行为。

但我仍然想知道:如果你觉得需要在你的equals方法中包含name ,显然你的id并不是唯一的。 那么为什么不在hashCode中包含name 这并不是很多额外的工作,特别是因为你可以生成一个从你的IDE,或者干脆使用java.util.Objects.hash(id, name)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM