What does a good equals method look like?

EqualsVerifier checks if you wrote your equals method the right way, but what is the right way?

Let’s say we have a class that looks like this:

public class Person {
    private final String name;
    private final int age;

    public Point(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // equals?
    // hashCode?
}

equals

A good equals method for this class looks like this:

    public boolean equals(Object obj) {
        return obj instanceof Person other &&
                Objects.equals(name, other.name) &&
                age == other.age;
    }

This makes use of Java 17’s pattern matching for instanceof feature. java.util.Objects.equals(a, b) takes care of null checks for non-primitive fields.

In prior versions of Java, it would look like this:

    public boolean equals(Object obj) {
        if (!(obj instanceof Person)) {
            return false;
        }
        Person other = (Person) obj;
        return Objects.equals(name, other.name) &&
                age == other.age;
    }

IDEs often generate an an instance check as the first line:

        if (this == obj) return true;

This is intended as an optimization. However, it turns out that, due to predictive branching optimizations that the JVM performs, this line actually makes equals slower in most cases, not faster. Therefore, I recommend leaving it out. See this video for more details.

hashCode

If you override equals in a class, you should always override hashCode as well. A good hashCode method for our Person class looks like this:

    public int hashCode() {
        return Objects.hash(name, age);
    }

Resources

If you want to know the reasoning behind all this, I recommend these resources:

  • Effective Java, Third Edition, items 10 (Obey the general contract when overriding equals) and 11 (Always override hashCode when you override equals)
    Addison-Wesley, 2018
    by Joshua Bloch
    [book]
  • How to Write an Equality Method in Java
    1 June 2009
    by Martin Odersky, Lex Spoon, and Bill Venners
    [link]
  • Not all equals methods are created equal
    7 November 2017
    by Jan Ouwens
    [video]
  • Optimizing your equals() methods with Pattern Matching - JEP Cafe #21
    9 November 2023
    by José Paumard
    [video]

Updated: