简体   繁体   中英

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.

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. Worth noticing is this hash method comply with all rules for 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?

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

Disclaimer: I'm the creator of 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. You want your hashCode distribution to be as large as possible, to ensure good performance when using hash-based collections.

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) .

But I still wonder: if you feel the need to include name in your equals method, apparently your id is not unique. Why then not also include name in hashCode? 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) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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