About Us Contact Us Write for Us Advertise
Home > Java > equals() and hashCode() in Java: Comparing Objects Correctly
Java

equals() and hashCode() in Java: Comparing Objects Correctly

Learn how equals() and hashCode() really work in Java, why you must override them together, and how they affect HashMap and HashSet — with clear beginner examples.

Shiv Pandey
Shiv Pandey
Sep 24, 2026 | 1 views
equals() and hashCode() in Java: Comparing Objects Correctly

Back in the Strings lesson you learned to compare text with .equals() instead of ==. This lesson goes one level deeper: what does equals() actually do, how do you make it work for your own objects, and why does its silent partner hashCode() matter so much? Get this right and your objects behave correctly inside collections; get it wrong and you'll hit bugs that are genuinely baffling. Let's make it clear.

== vs equals(), one more time

  • == checks if two references point to the exact same object in memory (identity).
  • .equals() checks if two objects are meaningfully equal (same content).

The catch: by default, a class you write inherits equals() from Object, and that default version just does ==. So unless you say otherwise, two "identical" objects are considered not equal:

class Point { int x, y; Point(int x,int y){this.x=x; this.y=y;} }

Point a = new Point(1, 2);
Point b = new Point(1, 2);

System.out.println(a == b);        // false — different objects
System.out.println(a.equals(b));   // false too! (default = ==)  — probably NOT what you want

Overriding equals()

To make two points with the same coordinates count as equal, we override equals() to compare the actual fields:

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof Point)) return false;
    Point p = (Point) o;
    return x == p.x && y == p.y;   // equal if fields match
}

Now a.equals(b) returns true — the behaviour you'd expect.

The golden rule: always override hashCode() too

If you override equals(), you MUST also override hashCode(). This is one of the most important rules in Java, and skipping it causes bugs that are very hard to track down. The contract is simple: two objects that are equal must return the same hashCode.

Why? Because HashMap and HashSet rely on it

Collections like HashMap and HashSet use hashCode() to decide where to store an object (which "bucket"), and only then use equals() to confirm a match. If two equal objects have different hash codes, they get filed in different buckets — so the collection thinks they're different, and lookups mysteriously fail:

Set<Point> set = new HashSet<>();
set.add(new Point(1, 2));
System.out.println(set.contains(new Point(1, 2)));
// WITHOUT hashCode(): false (!) — the bug
// WITH matching hashCode(): true — correct

Writing hashCode() (the easy way)

You almost never write the hashing maths by hand — Java gives you a helper. Just pass it the same fields you used in equals():

import java.util.Objects;

@Override
public int hashCode() {
    return Objects.hash(x, y);   // same fields as equals()
}

That's it. Use the same fields in both methods and the contract is satisfied.

The good news: your IDE (and Lombok) do this for you

In practice you rarely type these by hand. IntelliJ and Eclipse can generate correct equals() and hashCode() in two clicks, and libraries like Lombok add them with a single annotation. But — and this matters — you should understand what they generate and why, so you can spot the bug when it's missing.

This is one of those topics that seems academic until it bites you. I once spent an afternoon on a HashSet that kept adding "duplicate" objects — the cause was an equals() without a matching hashCode(). Ever since, I treat them as an inseparable pair: override one, override the other, using the same fields. Remember that single rule and you'll sidestep a bug that trips up even experienced developers.

Key takeaways

  • Default equals() just does ==; override it to compare your object's fields.
  • If you override equals(), always override hashCode() — using the same fields.
  • Equal objects must share the same hashCode, or HashMap/HashSet break.
  • Use Objects.hash(...), or let your IDE/Lombok generate both — but understand why.

← Previous: Lesson 24 — Enums & Wrapper Classes
Next: Lesson 26 — Immutability in Java →

Related Articles

Constructors in Java: Setting Up Objects the Right Way
Java

Constructors in Java: Setting Up Objects the Right Way

Classes and Objects in Java: The Foundation of OOP
Java

Classes and Objects in Java: The Foundation of OOP

Strings in Java: Methods, Comparison and the equals() Trap
Java

Strings in Java: Methods, Comparison and the equals() Trap

Enums and Wrapper Classes in Java Explained
Java

Enums and Wrapper Classes in Java Explained