简体   繁体   English

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

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

@Edit: I'm using this library http://jqno.nl/equalsverifier/ to check if equals and hashCode are written properly. @Edit:我正在使用这个库http://jqno.nl/equalsverifier/检查是否正确写入了equalshashCode

Let's say we have this class: 假设我们有这个课程:

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;
    }
}

In hashCode I'm relaying only on id field, because this will give me pretty good, non colliding hashes. hashCode我只在id字段上转发,因为这会给我很好的,非碰撞的哈希值。 Worth noticing is this hash method comply with all rules for equals-hashCode . 值得注意的是,这种hash方法符合equals-hashCode所有规则。 I don't want do some fancy tricks with summing hashes, ie this: 我不想做一些总结哈希的花哨技巧,即:

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

So could you explain me why EqualsVerifer by default demand using all fields from equals method in hashCode method? 所以你能解释一下为什么EqualsVerifer默认需要使用hashCode方法中equals方法的所有字段吗?

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

Disclaimer: I'm the creator of EqualsVerifier. 免责声明:我是EqualsVerifier的创建者。

The reason why it's the default behaviour, is because it's generally a good practice, and EqualsVerifier wants to encourage its users to follow good practices. 它是默认行为的原因是因为它通常是一种很好的做法,EqualsVerifier希望鼓励其用户遵循良好做法。 You want your hashCode distribution to be as large as possible, to ensure good performance when using hash-based collections. 您希望hashCode分布尽可能大,以确保在使用基于散列的集合时具有良好的性能。

If you have a good reason to do something else (and judging from your question, it seems like you may have one), you can always disable this behaviour by adding .suppress(Warning.STRICT_HASHCODE) . 如果您有充分的理由做其他事情(从您的问题判断,看起来您可能有),您可以通过添加.suppress(Warning.STRICT_HASHCODE)来禁用此行为。

But I still wonder: if you feel the need to include name in your equals method, apparently your id is not unique. 但我仍然想知道:如果你觉得需要在你的equals方法中包含name ,显然你的id并不是唯一的。 Why then not also include name in hashCode? 那么为什么不在hashCode中包含name It's not that much extra work, especially since you can generate one from your IDE, or simply use java.util.Objects.hash(id, name) . 这并不是很多额外的工作,特别是因为你可以生成一个从你的IDE,或者干脆使用java.util.Objects.hash(id, name)

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

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