Revquix
Mentors
Why Your HashMap Suddenly Stops Working (Even Though Nothing Changed)

Why Your HashMap Suddenly Stops Working (Even Though Nothing Changed)

  • Java
  • Java Interview Preparation
  • Java Collections Framework
  • Java Memory Model & JVM Internals
R
Rohit@rohit
Created 1mo ago·5 min read

The most dangerous bugs aren't the ones that crash your application... they're the ones that silently return the wrong result.

If you've been working with Java for a while, you've probably experienced something like this.

Your code compiles.

Your application starts normally.

No exceptions are thrown.

Yet somehow...

Java
map.get(key);

returns

Java
null

even though you just inserted that object into the map.

Sound impossible?

It isn't.

This is one of the most common interview questions - and one of the most expensive production bugs in Java applications.

Today, we'll uncover why HashMap sometimes appears to "forget" your data.


A Real Production Story

A fintech company stored customer sessions inside a HashMap.
Everything worked perfectly during testing.
A few days after deployment...
Random users started getting logged out.
The session clearly existed.
The logs showed it was successfully inserted.

But when retrieving it...

Java
sessionMap.get(session);

returned

Java
null

The infrastructure team spent two days investigating Redis.
The backend team blamed JVM memory.
Someone even suspected garbage collection.

The real culprit?
A single setter.


First, Let's Understand How HashMap Finds Your Object

HashMap does not search every key.

Instead, it performs three steps.

  1. Calculate the key's hash code.

  2. Find the correct bucket.

  3. Compare keys using equals().

It looks roughly like this.

Plain text
Key
   ↓
hashCode()
   ↓
Bucket Number
   ↓
equals()
   ↓
Value
image.png

Everything Works...

Imagine this class.

Java
class Employee {

    private int id;

    Employee(int id) {
        this.id = id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    public int hashCode() {
        return id;
    }

    @Override
    public boolean equals(Object obj) {
        Employee other = (Employee) obj;
        return this.id == other.id;
    }
}

Now let's use it.

Java
Map<Employee, String> employees = new HashMap<>();

Employee emp = new Employee(101);

employees.put(emp, "Rohit");

Everything looks perfectly fine.

Then Someone Changes the Object

Later...

Java
emp.setId(202);

Nothing seems wrong.
No exception.
No warning.
No compiler error.

Now try this.

Java
System.out.println(employees.get(emp));

Output

Java
null

Wait...

It is the same object.

How can HashMap lose it?


The Secret Lies Inside HashMap

When the object was inserted

Java
id = 101

HashMap calculated

Java
hashCode = 101

Suppose it stored the object inside

Java
Bucket 5

After changing

Java
id = 202;

the object's hash code also changed.

Now HashMap calculates

Java
hashCode = 202

which points to

Java
Bucket 12

But your object is still physically stored inside

Java
Bucket 5

HashMap searches Bucket 12.

The object lives in Bucket 5.

Result?

Java
null

image.png

Visual Representation

Before Mutation

After Mutation

Employee(101)

Employee(202)

hash = 101

hash = 202

Bucket 5

Bucket 12

Object stored in Bucket 5

Object still stored in Bucket 5

Lookup succeeds

Lookup fails

Why Doesn't HashMap Automatically Move It?

Because HashMap has no idea that your object's internal state changed.

It only performs rehashing when:

  • resizing

  • rebuilding buckets

  • inserting new entries during resize

It never watches your object's fields.

Doing so would make every lookup incredibly slow.


The Interview Twist

Many interviewers ask this question.

Can HashMap keys be mutable?

The technically correct answer is

Yes.

But they should never be mutable if those mutable fields participate in equals() or hashCode().

That's the important distinction.


Another Hidden Bug

Imagine this.

Java
HashSet<Employee> employees = new HashSet<>();

Employee emp = new Employee(10);

employees.add(emp);

emp.setId(20);

System.out.println(employees.contains(emp));

Output

Shell
false

Same root cause.

HashSet internally uses...

HashMap.


Why String Makes a Perfect HashMap Key

Have you ever wondered why Java developers frequently use

Java
Map<String, Object>

instead of

Java
Map<Employee, Object>

Because String is immutable.

Once created,

Java
String name = "Java";

it can never change.
Its hash code never changes.
Its bucket never changes.
Its lookup always works.

That's one of the major reasons Java made String immutable.


image.png

Best Practices

Always follow these rules.

  1. Use immutable keys.

  2. Never modify fields used in equals().

  3. Never modify fields used in hashCode().

  4. Override equals() and hashCode() together.

  5. Prefer records or immutable objects as map keys.

  6. Be extra careful when using Lombok's generated methods.


Production Impact

This bug can lead to:

  • Missing cache entries

  • Failed authentication

  • Duplicate records

  • Memory leaks

  • Incorrect business logic

  • Random production failures

  • Extremely difficult debugging sessions

The scary part?

No exception is ever thrown.


Common Interview Questions

Why does HashMap fail after modifying a key?

Because changing fields involved in hashCode() changes the computed bucket, but the entry remains stored in the original bucket.

Does HashMap move the object automatically?

No.

Does this happen in HashSet?

Yes, HashSet is backed by a HashMap.

Is this bug detectable by the compiler?

No, The code compiles successfully.


What's the safest key type?

  • String

  • Java Records

  • Immutable custom objects

  • Wrapper classes like Integer, Long, and UUID


Key Takeaways

HashMap doesn't lose your object.

You changed the address where it tries to find it.

Understanding this single concept separates developers who use Java collections from those who truly understand how they work internally.

The next time someone says:

"HashMap randomly stopped working."

You'll know exactly where to look.


Recommended Reading

HashMap (Java SE 21 & JDK 21)
declaration: module: java.base, package: java.util, class: HashMap
docs.oracle.com
Object (Java SE 21 & JDK 21)
declaration: module: java.base, package: java.lang, class: Object
docs.oracle.com

Enjoyed this article?

If you're preparing for Java interviews, aiming for Senior Software Engineer roles, or looking to strengthen your understanding of Java, Spring Boot, System Design, and Backend Development, I'd be happy to help.

👉 Book a 1:1 Career Mentorship Session or Mock Interview with me:

Let's work together to identify your knowledge gaps, improve your interview performance, and accelerate your software engineering career.

Discussion

?
0 / 5,000
Revquix
HomeServicesFind a MentorRevquix EditorialContact

© 2026 Revquix. All rights reserved.

PrivacyTerms