๐ Complete Guide to HashMap in Java
- Internal working
- Data structures used
- Hashing mechanism &
hashCode() - Collision handling
- What happens if two keys have the same
hashCode()? - Multithreading behavior
- Thread safety & making HashMap thread-safe
- Examples & proofs
Give me a moment to structure this in a clear, well-explained way for you!
๐น 1. What is HashMap?
HashMap in Java is a part of java.util package that stores key-value pairs using hashing.
It allows fast retrieval, insertion, and deletion in O(1) average time complexity.
โ Features:
- Stores data in (Key, Value) pairs.
- Allows one
nullkey but multiple null values. - Unordered, as it uses hashing.
- Not thread-safe by default.
import java.util.HashMap;public class HashMapExample {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "Java");
map.put(2, "Python");
map.put(3, "C++");
System.out.println(map); // Output: {1=Java, 2=Python, 3=C++}
}
}๐น 2. Internal Working of HashMap
๐ธ Data Structures Used
- Internally, HashMap uses an array of linked lists (or trees in some cases).
- This array is called a bucket array, where each index stores a linked list (or red-black tree) of entries.
// Internal representation (simplified)
class Node<K, V> {
K key;
V value;
int hash;
Node<K, V> next; // Linked list in case of collision
}๐ธ How HashMap Stores Elements?
1๏ธโฃ Computes the hashCode() of the key.
2๏ธโฃ Finds the bucket index using:
index = hash(key) % capacity;3๏ธโฃ Stores the key-value pair at the computed index.
๐น 3. Hashing and hashCode()
๐ธ What is Hashing?
Hashing is a technique to convert an input (key) into a fixed-size value (hash code) that determines where the key-value pair is stored.
public class HashCodeExample {
public static void main(String[] args) {
String key = "Hello";
int hashCode = key.hashCode();
System.out.println("HashCode of 'Hello': " + hashCode);
}
}โ Output:
HashCode of 'Hello': 69609650๐น 4. Hash Collision in HashMap
๐ธ What if Two Keys Have the Same hashCode()?
If two keys have the same hash code, a collision occurs.
๐ธ How HashMap Handles Collisions?
- Before Java 8: Uses a Linked List to store multiple values at the same bucket.
- After Java 8: Uses a Red-Black Tree if collisions become frequent (threshold > 8).
โ Example of Hash Collision Handling
import java.util.HashMap;class Key {
String value;
Key(String value) {
this.value = value;
}
@Override
public int hashCode() {
return 42; // Same hash code for all keys
}
@Override
public boolean equals(Object obj) {
return obj instanceof Key && this.value.equals(((Key) obj).value);
}
}public class HashMapCollision {
public static void main(String[] args) {
HashMap<Key, String> map = new HashMap<>();
map.put(new Key("One"), "Value1");
map.put(new Key("Two"), "Value2");
map.put(new Key("Three"), "Value3");
System.out.println(map); // All keys stored at same bucket, handled via LinkedList/Tree
}
}
๐น 5. HashMap in a Multithreading Environment
๐ธ Is HashMap Thread-Safe?
โ No, HashMap is NOT thread-safe.
Multiple threads modifying it concurrently may cause inconsistencies and infinite loops.
Get Yogesh Dahakeโs stories inย yourย inbox
Join Medium for free to get updates fromย thisย writer.
โ Example of Issue in Multithreading
import java.util.HashMap;public class HashMapThreadIssue {
static HashMap<Integer, String> map = new HashMap<>(); public static void main(String[] args) {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
map.put(i, "Value" + i);
}
}); Thread t2 = new Thread(() -> {
for (int i = 1000; i < 2000; i++) {
map.put(i, "Value" + i);
}
}); t1.start();
t2.start();
}
}
โ Possible Issues:
- Race conditions
- Data corruption
- Infinite loops due to concurrent modifications
๐น 6. Making HashMap Thread-Safe
๐ธ 1๏ธโฃ Using Collections.synchronizedMap()
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;public class SynchronizedHashMap {
public static void main(String[] args) {
Map<Integer, String> syncMap = Collections.synchronizedMap(new HashMap<>());
syncMap.put(1, "Java");
syncMap.put(2, "Python");
System.out.println(syncMap);
}
}โ
This makes HashMap thread-safe, but iteration still needs explicit synchronization.
๐ธ 2๏ธโฃ Using ConcurrentHashMap (Best Approach)
If multiple threads need to read and write, use ConcurrentHashMap instead of HashMap.
โ
It divides data into segments to allow multiple threads to modify different segments simultaneously.
import java.util.concurrent.ConcurrentHashMap;public class ConcurrentHashMapExample {
public static void main(String[] args) {
ConcurrentHashMap<Integer, String> map = new ConcurrentHashMap<>();
map.put(1, "Java");
map.put(2, "Python"); System.out.println(map);
}
}
โ
Advantages of ConcurrentHashMap over HashMap:
- Thread-safe without explicit synchronization.
- Faster than
synchronizedMap()since it allows multiple threads to operate on different parts.
๐น 7. Summary Table
Aspect Details Data Structure Uses array of Linked Lists (before Java 8), Red-Black Trees (after Java 8) Insertion Time Complexity O(1) (average case) Thread Safety โ Not thread-safe Handling Collisions โ
Uses chaining (linked list/tree) If two keys have same hashCode()? โ
They are stored in a linked list or tree at the same bucket Making it Thread-Safe โ
Use Collections.synchronizedMap() or ConcurrentHashMap
๐น 8. Final Thoughts
๐น HashMap is a powerful data structure, but it's not thread-safe by default.
๐น Use ConcurrentHashMap for thread-safe operations in multi-threaded environments.
๐น Always handle hashCode() and equals() properly to avoid unintended behavior.







