The HashMap class is the most common implementation of the Map interface. It stores data in (Key, Value) pairs, and you can access them by an index of another type (e.g. a String).
It uses a hash table to store the map. This allows the execution time of get() and put() to remain constant (O(1)) on average, regardless of the size of the map.
null: A HashMap can have one null key and multiple null values.get and put operations on average.HashMap WorksSimilar to HashSet, a HashMap uses the key's hashCode() method to determine where to store the (Key, Value) entry. When you want to retrieve a value, it uses the key's hashCode() to find the location, and then uses the key's equals() method to find the exact entry if multiple keys have the same hash code (a "collision").
Important: If you use custom objects as keys in a
HashMap, you must properly implement both thehashCode()andequals()methods in your key class.
💡 The "Kitchen Pantry" Analogy: Imagine your kitchen pantry is a
HashMap.
- You have a jar labeled "Spices." The label "Spices" is the
hashCode(). It quickly tells you which shelf to look on.- When you get to that shelf, you see several jars: salt, pepper, and paprika. They all have the same "Spices" label (a hash collision!).
- To find the exact one you want (salt), you have to read the name on each jar. This is the
equals()method. It confirms you have the correct object. Without a properhashCode()(label), you wouldn't know which shelf to check. Withoutequals(), you couldn't tell the jars apart.
HashMapHashMap is the ideal choice when you need to map keys to values and:
It is the most frequently used Map implementation in Java.
Here is an example demonstrating common operations on a HashMap.
import java.util.HashMap; import java.util.Map;public class Main { public static void main(String[] args) { // Create a HashMap to cache user settings Map<String, String> userSettings = new HashMap<>(); // Add user settings userSettings.put("userId", "akash-123"); userSettings.put("theme", "dark"); userSettings.put("language", "en-US"); userSettings.put("notifications", "enabled"); System.out.println("Initial Settings: " + userSettings); // Access an item String theme = userSettings.get("theme"); System.out.println("Current Theme: " + theme); // Update an item (keys are unique, so this replaces the old value) userSettings.put("theme", "light"); System.out.println("Updated Settings: " + userSettings); // Remove an item userSettings.remove("notifications"); System.out.println("After removing notifications: " + userSettings); // Get the size System.out.println("Number of settings: " + userSettings.size()); // Loop through the HashMap System.out.println("\n--- Iterating through settings ---"); for (Map.Entry<String, String> entry : userSettings.entrySet()) { System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue()); } } }
getOrDefault() (Java 8+)A very common problem when reading from a map is handling cases where a key doesn't exist. Instead of writing if checks to prevent NullPointerExceptions, Java 8 introduced getOrDefault().
import java.util.HashMap;public class Main { public static void main(String[] args) { HashMap<String, Integer> scores = new HashMap<>(); scores.put("Alice", 85); // Bob doesn't exist in the map, so it returns the default value (0) int bobScore = scores.getOrDefault("Bob", 0); System.out.println("Bob's Score: " + bobScore); // Outputs 0 } }
Never use a **mutable object** (an object whose state can change) as a key in a `HashMap`. If you modify the key object after it has been inserted into the map, its `hashCode()` might change. When this happens, the `HashMap` will be unable to find the entry, leading to a memory leak and bugs that are incredibly difficult to trace. Always use immutable objects like `String`, `Integer`, or your own custom immutable classes for keys.
A Hash Collision occurs when two completely different keys produce the exact same hashCode(), meaning they are assigned to the same "bucket" in the underlying hash table.
Historically, HashMap handled collisions by placing the entries in a linked list inside that bucket, which degrades performance to O(n) if many collisions occur.
Java 8 Optimization: To protect against this performance degradation (which could be exploited in Denial of Service attacks), Java 8 updated HashMap. When a single bucket accumulates too many collisions (specifically, 8 or more), the linked list is automatically converted into a balanced Red-Black Tree, restoring performance to O(log n) for those problematic buckets!
What is the average time complexity for `get()` and `put()` operations in a HashMap?