Java.Core.What happens if you override equals() without overriding hashCode()? What problems might arise?

What Happens If You Override equals() Without Overriding hashCode()?

If you override equals() but do not override hashCode(), you violate the contract between equals() and hashCode(). This can lead to unexpected behavior in hash-based collections like HashSet, HashMap, and HashTable.


🚀 Why Is This a Problem?

The Java contract between equals() and hashCode() states:

  1. If two objects are equal (a.equals(b) == true), then a.hashCode() == b.hashCode() must also be true.
  2. If two objects have different hash codes (a.hashCode() != b.hashCode()), then a.equals(b) must return false.
  3. If two objects have the same hash code (a.hashCode() == b.hashCode()), they may or may not be equal (a.equals(b) may be true or false).
    • (This is because hash collisions can occur.)

🔴 Problems That Arise

1. Hash-Based Collections Will Misbehave

Hash-based collections (HashMap, HashSet, HashTable) use hashCode() for bucketing and equals() for checking equality. If hashCode() is not overridden, objects that are considered equal may end up in different hash buckets, causing duplicate entries or lookup failures.

Example: HashSet Stores Duplicates Unexpectedly

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj;
        return Objects.equals(name, person.name);
    }
    // ❌ No hashCode() override!
}

public class Main {
    public static void main(String[] args) {
        Set<Person> set = new HashSet<>();
        Person p1 = new Person("Alice");
        Person p2 = new Person("Alice");

        set.add(p1);
        set.add(p2);

        System.out.println(set.size()); // ❌ Expected: 1, but prints: 2
    }
}

What Went Wrong?

  • p1.equals(p2) returns true, meaning they should be considered the same object.
  • But since hashCode() is not overridden, p1 and p2 get different hash codes (from Object.hashCode()).
  • As a result, they are stored in different hash buckets, causing duplicates.

2. HashMap and HashTable Key Lookups Will Fail

If you use an object as a key in a HashMap and override equals() but not hashCode(), key lookups may fail.

Example: HashMap Key Lookup Fails

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj;
        return Objects.equals(name, person.name);
    }
    // ❌ No hashCode() override!
}

public class Main {
    public static void main(String[] args) {
        Map<Person, String> map = new HashMap<>();
        Person p1 = new Person("Alice");
        map.put(p1, "Developer");

        Person p2 = new Person("Alice"); // Different object but equal by equals()
        System.out.println(map.get(p2)); // ❌ Expected: "Developer", but prints: null
    }
}

What Went Wrong?

  • p1.equals(p2) is true, meaning they should be the same key.
  • But p1.hashCode() and p2.hashCode() are different (because hashCode() is not overridden).
  • HashMap looks for p2 in a different hash bucket, so it does not find the value.

3. Performance Issues in Large Collections

  • If hashCode() is not overridden, all objects may end up in different hash buckets, causing poor performance.
  • Instead of O(1) lookup time, operations may degrade to O(n) time complexity due to linear search within buckets.

✅ Correct Implementation: Override equals() and hashCode()

To fix these issues, always override hashCode() whenever you override equals().

Fixed Version

import java.util.Objects;
import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;

class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj;
        return Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name); // ✅ Includes name in hashCode
    }
}

public class Main {
    public static void main(String[] args) {
        // HashSet test
        Set<Person> set = new HashSet<>();
        Person p1 = new Person("Alice");
        Person p2 = new Person("Alice");
        set.add(p1);
        set.add(p2);

        System.out.println(set.size()); // ✅ Correct: Prints 1

        // HashMap test
        Map<Person, String> map = new HashMap<>();
        map.put(p1, "Developer");

        System.out.println(map.get(p2)); // ✅ Correct: Prints "Developer"
    }
}

📌 Summary: Why You MUST Override hashCode() With equals()

IssueWhat Happens Without hashCode()?Why Overriding Fixes It
Duplicate Entries in HashSetset.add(obj1) and set.add(obj2) both store objects, even if equals() says they are the same.Objects with equal contents will have the same hash code, so duplicates are avoided.
Failed Lookups in HashMapmap.get(new Key("Alice")) returns null, even though "Alice" is already a key.Ensures that equal keys have the same hash code, so lookups work correctly.
Slow PerformanceSearching for an element in a hash-based collection degrades from O(1) to O(n).Objects are placed in the correct hash bucket, making searches efficient.

🔹 Final Best Practices

Always override hashCode() when overriding equals().
Use Objects.hash() for simple and safe hashCode() implementation.
Follow the contract: a.equals(b) == truea.hashCode() == b.hashCode().
Test hash-based collections (HashSet, HashMap) when overriding these methods.

This entry was posted in Без рубрики. Bookmark the permalink.