DEV Community

realNameHidden
realNameHidden

Posted on

đź§© What Happens If You Override hashCode() But Not equals() in Java?

Learn what happens if you override hashCode() but not equals() in Java. Understand how this impacts HashMap, HashSet, and your object comparisons with simple examples.


Introduction

Imagine you’ve created a group of friends in your Java program — say, a HashSet of Person objects. You add two people who look identical (same name, age, etc.), but Java still thinks they’re different!

Confused? Many Java developers — even experienced ones — get puzzled by this. The reason lies in how equals() and hashCode() work together behind the scenes.

These two methods are like best friends — they must agree with each other. If you override one without the other, it can cause strange, hard-to-debug behavior, especially when using collections like HashMap, HashSet, or Hashtable.

In this post, we’ll explore what happens if you override hashCode() but not equals(), using simple analogies, examples, and best practices to help you write reliable, predictable Java code.


Core Concepts: Understanding equals() and hashCode()

Every Java object inherits two crucial methods from the Object class:

🟢 equals(Object obj)

Determines if two objects are meaningfully equal — for example, two Person objects having the same name and age.

By default, equals() in Object checks reference equality, meaning two objects are equal only if they are the exact same instance in memory.

You usually override equals() to define logical equality, e.g., comparing object contents instead of memory addresses.


🟣 hashCode()

Generates an integer hash value used to store and locate objects efficiently in hash-based collections such as:

  • HashMap
  • HashSet
  • LinkedHashMap

Objects that are equal according to equals() must return the same hash code. This is the famous equals()–hashCode() contract in Java.


⚠️ The Contract Between equals() and hashCode()

Here’s the rule, straight from the Java specification:

If two objects are equal according to equals(), they must have the same hashCode().

However, the reverse is not required — two objects can have the same hash code but not be equal.

This ensures that collections like HashSet and HashMap can find and manage objects efficiently.


🚨 What Happens If You Override Only hashCode()?

If you override hashCode() but leave equals() untouched:

  • Two objects with the same data may produce the same hash code.
  • But since equals() still checks for reference equality, Java considers them unequal.
  • As a result, collections like HashSet will store duplicates because they think they’re different objects!

This breaks the intended logic of “equal objects should not repeat.”

Let’s see this in action.


Code Examples

Example 1: Overriding hashCode() But Not equals()

// Java 21 Example
import java.util.HashSet;

class Person {
    private String name;
    private int age;

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

    // ❌ Only hashCode is overridden
    @Override
    public int hashCode() {
        return name.hashCode() + age;
    }
}

public class HashCodeOnlyExample {
    public static void main(String[] args) {
        Person p1 = new Person("Alice", 25);
        Person p2 = new Person("Alice", 25);

        System.out.println("p1.hashCode(): " + p1.hashCode());
        System.out.println("p2.hashCode(): " + p2.hashCode());
        System.out.println("Are p1 and p2 equal? " + p1.equals(p2));

        HashSet<Person> people = new HashSet<>();
        people.add(p1);
        people.add(p2);

        System.out.println("HashSet size: " + people.size());
    }
}
Enter fullscreen mode Exit fullscreen mode

đź§  Output Explanation:

p1.hashCode(): 63459
p2.hashCode(): 63459
Are p1 and p2 equal? false
HashSet size: 2
Enter fullscreen mode Exit fullscreen mode

Even though both Person objects have identical data and same hash code, equals() wasn’t overridden — so Java treats them as different.
Your HashSet ends up storing duplicates, breaking its uniqueness property.


Example 2: Overriding Both equals() and hashCode()

// Java 21 Example
import java.util.HashSet;
import java.util.Objects;

class PersonProper {
    private String name;
    private int age;

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

    // âś… Correctly override equals()
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;               // same object
        if (obj == null || getClass() != obj.getClass()) return false;
        PersonProper other = (PersonProper) obj;
        return age == other.age && Objects.equals(name, other.name);
    }

    // âś… Correctly override hashCode()
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

public class HashCodeEqualsExample {
    public static void main(String[] args) {
        PersonProper p1 = new PersonProper("Alice", 25);
        PersonProper p2 = new PersonProper("Alice", 25);

        System.out.println("Are p1 and p2 equal? " + p1.equals(p2));

        HashSet<PersonProper> people = new HashSet<>();
        people.add(p1);
        people.add(p2);

        System.out.println("HashSet size: " + people.size());
    }
}
Enter fullscreen mode Exit fullscreen mode

đź§  Output Explanation:

Are p1 and p2 equal? true
HashSet size: 1
Enter fullscreen mode Exit fullscreen mode

Now both objects are considered equal, and the HashSet properly avoids duplication.
This is how Java’s equals()–hashCode() partnership is meant to work.


Best Practices

  1. Always Override Both equals() and hashCode() Together
    Whenever you define one, make sure the other is implemented consistently.

  2. Use Objects.equals() and Objects.hash()
    Introduced in Java 7, these utility methods simplify your code and handle null values safely.

  3. Don’t Use Mutable Fields in Hashing or Equality
    Changing fields used in equals() or hashCode() after inserting an object into a HashSet or HashMap can lead to unpredictable results.

  4. Follow IDE Suggestions
    Most modern IDEs (like IntelliJ IDEA or Eclipse) can auto-generate correct implementations of equals() and hashCode() — use them!

  5. Test Equality Logic Thoroughly
    Create test cases where two objects should be equal and where they shouldn’t. Verify both hash code consistency and equality.


Conclusion

In Java programming, equals() and hashCode() are like two wheels on a bike — if one’s missing or misaligned, your program won’t go far!

If you override only hashCode() and not equals(), collections like HashMap and HashSet may behave unpredictably — treating identical objects as different ones.

To keep your data structures accurate and your code predictable, always override both together, ensuring they follow Java’s contract. It’s a small habit that prevents big debugging headaches later.


Top comments (0)