Why Overriding hashCode and equals Is Essential for Custom Keys in Java HashMap
This article explains how HashMap stores data using hash functions, illustrates the impact of hash collisions, and demonstrates with Java code why custom objects used as keys must override both hashCode and equals to work correctly in interviews and real projects.
During Java junior developer interviews, a common question is whether the candidate has ever overridden the hashCode method. To verify the answer, interviewers often ask if the candidate has ever used a custom object as a key in a HashMap . This article starts from the basics of hash tables to clarify the correct answer.
First, we review the concept of a hash table: unlike a linear list where searching requires scanning half the elements on average, a hash table can locate an element in near‑constant time because the position is determined by a hash function. For illustration, a simple hash function x*x%5 maps values to an array of length 11, showing how values like 6 and 7 are placed directly at their computed indices.
When two different keys produce the same hash value, a collision occurs. Java’s HashMap resolves collisions using the chaining method, creating a linked list at the colliding index.
To demonstrate the problem of not overriding hashCode and equals , the article presents the following Java program:
1 import java.util.HashMap;
2 class Key {
3 private Integer id;
4 public Integer getId() { return id; }
5 public Key(Integer id) { this.id = id; }
6 // intentionally comment out equals and hashCode
7 // public boolean equals(Object o) {
8 // if (o == null || !(o instanceof Key)) { return false; }
9 // else { return this.getId().equals(((Key) o).getId()); }
10 // }
11 // public int hashCode() { return id.hashCode(); }
12 }
13
14 public class WithoutHashCode {
15 public static void main(String[] args) {
16 Key k1 = new Key(1);
17 Key k2 = new Key(1);
18 HashMap
hm = new HashMap<>();
19 hm.put(k1, "Key with id is 1");
20 System.out.println(hm.get(k2)); // prints null
21 }
22 }In this example, k1 and k2 have the same logical identifier but are distinct objects. Because Key does not override hashCode , the default implementation returns the objects’ memory addresses, causing different hash values and preventing hm.get(k2) from finding the entry.
After uncommenting the hashCode method, both keys produce the same hash value (the hash of id ). However, without overriding equals , HashMap still cannot consider the two keys equal, because the default equals compares memory addresses.
The article shows that even with matching hash codes, the lookup fails unless equals is also overridden to compare the logical state (the id field). This explains why the interview question focuses on both methods.
Finally, the author emphasizes that whenever custom objects are used as keys in a HashMap , developers must provide proper implementations of both hashCode and equals to ensure correct behavior, a point that should be highlighted in interviews.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.