⚠️ 1. Poor equals()
and hashCode()
implementation
If you create your own key class and don’t override equals()
and hashCode()
properly, HashMap won’t be able to:
- Find existing entries correctly,
- Prevent duplicate keys,
- Replace values correctly.
🔥 Example:
class MyKey {
int id;
MyKey(int id) { this.id = id; }
// Oops! No hashCode() or equals()
}
Map<MyKey, String> map = new HashMap<>();
map.put(new MyKey(1), "A");
map.put(new MyKey(1), "B");
System.out.println(map.size()); // Output: 2 (should be 1)
➡️ Both keys look logically equal but go to different buckets, so the first value becomes unreachable — effectively “lost”.
⚠️ 2. Mutating a key after insertion
If a key’s fields that affect hashCode()
or equals()
are modified after the key is put into the map, the map can no longer find it.
🔥 Example:
MyKey key = new MyKey(1);
map.put(key, "A");
key.id = 2; // Changes hashCode()
map.get(key); // Returns null ❌
➡️ The key has moved logically, but the map still looks in the old bucket → can’t find it.
⚠️ 3. Concurrency issues (without synchronization)
If multiple threads modify a HashMap without proper synchronization, weird things can happen:
- Data loss,
- Infinite loops,
- Even internal corruption (in Java 7 and earlier — concurrent resizing could cause circular references).
💡 Always use ConcurrentHashMap
or proper synchronization for thread-safe access.
⚠️ 4. Collision overwriting
If multiple keys hash to the same bucket and equals()
incorrectly treats them as equal, a new put() may overwrite an existing one, losing the previous value.
✅ Safe practices to avoid “lost” elements:
- Always override both
hashCode()
andequals()
in key classes. - Make key fields immutable.
- Use proper thread-safe collections in multithreaded code.
- Avoid relying on default implementations of
hashCode()
andequals()
fromObject
.