HashMap is the most widely used data structure in Java Collections. It stores data as key-value pairs and provides average O(1) time complexity for insertion, deletion, and lookup.
Defined in:
java.util.HashMapA HashMap is based on:
- Hashing
- Array + LinkedList + Red-Black Tree hybrid structure
hashCode()andequals()contract
It allows:
- One null key
- Multiple null values
- Non-synchronized operations (not thread-safe)
Internally, HashMap uses:
Array of buckets
Each bucket → LinkedList or Tree (Java 8+)
Conceptually:
Index 0 → Entry → Entry → ...
Index 1 → Entry
Index 2 → null
Index 3 → Entry → Entry → ...
Each entry is stored as a Node:
static class Node<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
}HashMap heavily depends on two methods from Object class:
public int hashCode();
public boolean equals(Object obj);- Returns an integer hash of the key
- Used to compute bucket index
- Same key must produce same hashcode
- Used to resolve collisions
- Confirms if two objects are actually equal
- If
a.equals(b)is true →a.hashCode() == b.hashCode()must be true - If
hashCode()is same → objects may or may not be equal
Breaking this contract leads to:
- Duplicate keys
- Unpredictable behavior
- Lookup failure
Steps:
- Take
hashCode() - Apply
hash()function to reduce collisions - Compute index using modulo:
index = hash & (n - 1)
Where n is table capacity.
This bitwise operation is faster than %.
map.put("A", 10);- Compute hash from
"A".hashCode() - Compute bucket index
- Check if bucket is empty
- Node inserted directly
Collision happens when multiple keys map to same index
HashMap handles collisions using:
- Linked List (before Java 8)
- Linked List + Tree (after Java 8)
- Compare hash
- If hash equal → check
equals() - If key exists → value replaced
- Else → append node to list
When bucket linked list size exceeds 8, structure converts into Red-Black Tree improving performance from:
O(n) → O(log n)
Tree converts back to list if size falls below 6.
map.get("A");- Compute hash
- Compute bucket index
- Traverse bucket
- Compare:
- First by hash
- Then by equals()
If found → return value If not found → return null
Time complexity:
- Average: O(1)
- Worst case (all keys same bucket): O(n)
- With tree structure: O(log n)
map.remove("A");- Compute hash
- Compute index
- Locate bucket
- Traverse linked list / tree
- Match key using equals()
- Remove node
- Re-link neighbors
Time complexity:
- Average: O(1)
- Worst-case: O(n)
- Tree bucket: O(log n)
Reason:
- Direct index access using hash
- No need to scan full collection
- Constant-time bucket addressing
Mathematically:
O(1) expected because hash distributes keys uniformly
Becomes O(n) only when:
- Poor hash function
- All keys land in one bucket
- High collision rate
Default:
0.75
Formula:
resize threshold = capacity * load factor
Example:
- default capacity = 16
- threshold = 16 * 0.75 = 12
When size exceeds 12 → HashMap resizes to 32 buckets
- Creates bigger array
- Recomputes bucket indices
- Expensive operation
Interview tip: Avoid resizing by initializing map with expected size.
Stored in bucket 0
Reason:
- null has no hashCode
- JVM uses fixed bucket
Allowed multiple times
Iterators throw:
ConcurrentModificationException
If HashMap is modified during iteration except through iterator methods.
HashMap is not thread-safe. Use:
ConcurrentHashMap- or
Collections.synchronizedMap
for concurrency.
| Method | Purpose |
|---|---|
| hashCode() | Generates hash value |
| equals() | Confirms key equality |
| resize() | Expands capacity |
| putVal() | Inserts key-value mapping |
| getNode() | Retrieves node for key |
| treeifyBin() | Converts bucket list to tree |
class Student {
int id;
Student(int id) {
this.id = id;
}
public int hashCode() {
return id;
}
public boolean equals(Object obj) {
Student s = (Student) obj;
return this.id == s.id;
}
}Usage:
Map<Student, String> map = new HashMap<>();
map.put(new Student(1), "John");
System.out.println(map.get(new Student(1))); // JohnWithout overriding these methods, get() would return null.
- Index calculated through hashing
- Direct bucket access
- Severe collision
- Poor hash function
- Single bucket chain growth
- hashCode() → bucket location
- equals() → key equality check inside bucket
- Only one
- 8 nodes per bucket
- No
- Use ConcurrentHashMap instead
-
HashMap uses hashing to locate buckets
-
Operations are O(1) on average
-
Buckets use LinkedList and Red-Black Trees
-
hashCode() and equals() define key uniqueness
-
Resizing happens after load factor threshold
-
Supports one null key and multiple null values
-
Not thread-safe