HashMap
HashMap is the most widely used implementation of the Map interface in Java. It stores data as key–value pairs, provides fast lookup, and is optimized for high-performance, non-thread-safe scenarios. This is a top-tier interview topic and heavily used in real-world Java systems.
What Is HashMap?
- Implementation of Map interface
- Stores data as key–value pairs
- Keys are unique, values can be duplicated
- No insertion order guarantee
- Allows one null key and multiple null values
- Part of java.util package
Map<Integer, String> map = new HashMap<>();
Position in Map Hierarchy
Map
└── HashMap
Key Characteristics of HashMap
- Unordered collection
- Fast operations (O(1) average)
- Uses hashing
- Not synchronized (not thread-safe)
- Allows null key and values
How HashMap Works Internally (Very Important – Interview Favorite)
Step-by-step:
- Key’s hashCode() is called
- Hash value is converted into an index (bucket)
- If bucket is empty → entry stored
- If bucket already has entries:
- equals() is used to check key equality
- If key exists → value replaced
- If not → new entry added
Internal Data Structure
- Internally uses an array of buckets
- Each bucket stores:
- Linked List (Java 7 and below)
- Linked List → Red-Black Tree (Java 8+, if collisions exceed threshold)
- ✔ Improves performance during high collisions
Important Internal Parameters
1️⃣ Initial Capacity
Default = 16
2️⃣ Load Factor
Default = 0.75
3️⃣ Rehashing
Occurs when:
size > capacity × loadFactor
✔ HashMap resizes (doubles capacity)
Creating a HashMap
HashMap<String, Integer> map = new HashMap<>();
With Initial Capacity
HashMap<String, Integer> map = new HashMap<>(32);
Commonly Used HashMap Methods
Adding / Updating Entries
map.put(1, "Java");
map.put(2, "Python");
map.put(1, "C++"); // replaces value
Accessing Values
map.get(1);
map.getOrDefault(3, "NA");
Removing Entries
map.remove(2);
Checking Keys and Values
map.containsKey(1);
map.containsValue("Java");
Iterating HashMap (Best Practice)
for (Map.Entry<Integer, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue());
}
Duplicate Key Behavior
map.put(1, "Java");
map.put(1, "Python");
System.out.println(map); // {1=Python}
- ✔ Duplicate key replaces old value
- ✔ No exception thrown
Null Handling
map.put(null, "Java"); // allowed
map.put(null, "Python"); // replaces value
map.put(1, null);
map.put(2, null); // multiple null values allowed
Performance Complexity
| Operation | Time Complexity |
|---|---|
| put | O(1) average |
| get | O(1) average |
| remove | O(1) |
| iteration | O(n) |
⚠ Worst case: O(n) (hash collisions)
HashMap vs Hashtable (Interview Comparison)
| Feature | HashMap | Hashtable |
|---|---|---|
| Thread-safe | ❌ No | ✔ Yes |
| Null key | ✔ One | ❌ No |
| Null values | ✔ Yes | ❌ No |
| Performance | Faster | Slower |
| Legacy | ❌ No | ✔ Yes |
HashMap vs LinkedHashMap vs TreeMap
| Feature | HashMap | LinkedHashMap | TreeMap |
|---|---|---|---|
| Order | ❌ No | ✔ Insertion | ✔ Sorted |
| Performance | Fastest | Slightly slower | Slower |
| Null key | ✔ One | ✔ One | ❌ No |
Common Beginner Mistakes
- Assuming insertion order
- Using mutable objects as keys
- Not overriding equals() and hashCode()
- Using HashMap in concurrent code
- Ignoring initial capacity tuning
Best Practices
- Always override equals() and hashCode() for custom key objects
- Use immutable keys
- Set initial capacity when size is known
- Use ConcurrentHashMap for multithreading
- Iterate using entrySet()
Interview-Ready Answers
Short Answer
HashMap is a Map implementation that stores key–value pairs using hashing.
Detailed Answer
In Java, HashMap implements the Map interface and stores entries using a hash table. It allows one null key, multiple null values, and provides constant-time performance for get and put operations. It uses hashCode() and equals() to ensure key uniqueness and is not thread-safe.
Key Takeaway
HashMap offers the best performance for key-based lookups when ordering and thread safety are not required. Correct key design (equals() + hashCode()) is critical for correctness and performance.
HashMap Examples
1. Creating a HashMap
import java.util.*;
class Demo {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "Java");
map.put(2, "API");
System.out.println(map);
}
}
Output
{1=Java, 2=API}
2. Duplicate Key Overwrites Value
import java.util.*;
class Demo {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "Java");
map.put(1, "Selenium");
System.out.println(map);
}
}
Output
{1=Selenium}
3. Duplicate Values Are Allowed
import java.util.*;
class Demo {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "Test");
map.put(2, "Test");
System.out.println(map);
}
}
4. HashMap Allows One null Key
import java.util.*;
class Demo {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
map.put(null, "Value1");
map.put(null, "Value2");
System.out.println(map);
}
}
Output
{null=Value2}
5. HashMap Allows Multiple null Values
import java.util.*;
class Demo {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
map.put(1, null);
map.put(2, null);
System.out.println(map);
}
}
6. Retrieving Value Using get()
import java.util.*;
class Demo {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
map.put(10, "Java");
System.out.println(map.get(10));
}
}
Output
Java
7. get() with Missing Key
import java.util.*;
class Demo {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
System.out.println(map.get(1));
}
}
Output
null
8. Checking Key & Value
import java.util.*;
class Demo {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "Java");
System.out.println(map.containsKey(1));
System.out.println(map.containsValue("Java"));
}
}
Output
true
true
9. Iterating Using entrySet() (Best Practice)
import java.util.*;
class Demo {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "A");
map.put(2, "B");
for (Map.Entry<Integer, String> e : map.entrySet()) {
System.out.println(e.getKey() + " = " + e.getValue());
}
}
}
10. Iterating Using keySet()
import java.util.*;
class Demo {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "X");
map.put(2, "Y");
for (Integer k : map.keySet()) {
System.out.println(k + " -> " + map.get(k));
}
}
}
11. Iterating Using values()
import java.util.*;
class Demo {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "Java");
map.put(2, "API");
for (String v : map.values()) {
System.out.println(v);
}
}
}
12. Removing Entry by Key
import java.util.*;
class Demo {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "Java");
map.remove(1);
System.out.println(map);
}
}
Output
{}
13. Conditional Remove
import java.util.*;
class Demo {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "Java");
map.remove(1, "API"); // no effect
map.remove(1, "Java"); // removed
System.out.println(map);
}
}
14. putIfAbsent()
import java.util.*;
class Demo {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "Java");
map.putIfAbsent(1, "API");
map.putIfAbsent(2, "API");
System.out.println(map);
}
}
Output
{1=Java, 2=API}
15. replace() Method
import java.util.*;
class Demo {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "Java");
map.replace(1, "Selenium");
System.out.println(map);
}
}
16. computeIfAbsent()
import java.util.*;
class Demo {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
map.computeIfAbsent(1, k -> "Generated");
System.out.println(map);
}
}
17. Custom Object as Key (Without equals & hashCode)
class User {
int id;
User(int id) { this.id = id; }
}
import java.util.*;
class Demo {
public static void main(String[] args) {
HashMap<User, String> map = new HashMap<>();
map.put(new User(1), "Admin");
map.put(new User(1), "Admin");
System.out.println(map.size());
}
}
Output
2
18. Custom Object as Key (With equals & hashCode)
class User {
int id;
User(int id) { this.id = id; }
public boolean equals(Object o) {
return this.id == ((User)o).id;
}
public int hashCode() {
return id;
}
}
import java.util.*;
class Demo {
public static void main(String[] args) {
HashMap<User, String> map = new HashMap<>();
map.put(new User(1), "Admin");
map.put(new User(1), "Admin");
System.out.println(map.size());
}
}
Output
1
19. Thread-Unsafe Nature of HashMap
import java.util.*;
class Demo {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
map.put("A", "Not Thread Safe");
System.out.println(map);
}
}
Explanation
Use ConcurrentHashMap for concurrency.
20. Interview Summary – HashMap
import java.util.*;
class Demo {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "Fast");
map.put(2, "Unordered");
map.put(null, "OneNullKey");
System.out.println(map);
}
}
Key Points
- Key-value structure
- Keys are unique
- One null key allowed
- Multiple null values allowed
- Backed by buckets (hashing)
- Average time: O(1)