A Map is an object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value. While technically not a subtype of the Collection interface, it is a core pillar of the Java Collections Framework.
In a Map, data is stored in entries. An Entry is a simple object containing a Key and its associated Value. The Key acts as a unique identifier used to retrieve the Value later.
Must be unique. If you put a new value with an existing key, the old value is overwritten. Usually, keys are immutable (like String or Integer).
Can be duplicated. Multiple different keys can point to the same value (e.g., two people can have the same birth year).
Just like Sets, Maps come in different flavors depending on your requirements for speed, ordering, and sorting.
| Implementation | Ordering | Null Support | Performance |
|---|---|---|---|
| HashMap | None (Unpredictable) | 1 Null Key, Many Null Values | $O(1)$ |
| LinkedHashMap | Insertion Order | 1 Null Key, Many Null Values | $O(1)$ |
| TreeMap | Sorted (by Key) | No Null Keys | $O(\log n)$ |
| Hashtable | None (Legacy) | No Nulls (Thread-safe) | $O(1)$ but slow |
Interacting with a Map requires a different set of methods than a List or Set:
V put(K key, V value): Adds a pair. Returns the previous value associated with the key, or null.V get(Object key): Retrieves the value. Returns null if the key doesn't exist.boolean containsKey(Object key): Checks if a key exists ($O(1)$ for HashMap).Set<K> keySet(): Returns a Set of all keys in the map.Collection<V> values(): Returns a Collection of all values.Set<Map.Entry<K, V>> entrySet(): Returns a Set of key-value pairs (Best for iteration).When you call map.put("Java", 100), Java doesn't just store the string. It calculates a Hash Code for the key "Java," determines a bucket index, and stores the Entry object there. This is why lookups are nearly instantaneous regardless of whether the map has 10 or 10 million items.
This example demonstrates how to store custom objects in a map and iterate through them efficiently using the entrySet.
Java 8 revolutionized how we work with Maps by introducing functional methods that reduce boilerplate code:
computeIfAbsent(key, mappingFunction): Only computes a value if the key isn't already there. Perfect for initializing nested collections.merge(key, value, remappingFunction): Combines the existing value with a new value. Great for counters.forEach((k, v) -> ...): Clean, lambda-based iteration.Never change a key while it is in a Map. If you use a custom User object as a key and then change the user's ID, the hashCode() will change. The Map will look for the user in the "new" bucket, fail to find it, and you will have an orphaned entry in the "old" bucket that can never be retrieved or deleted. This is why String is the most common key—it is immutable.
Q: Why doesn't Map extend Collection?
A: A Collection is a group of individual items. A Map is a group of pairs. The methods are fundamentally different (e.g., add(E e) vs put(K k, V v)). Mixing them would violate the Interface Segregation Principle.
Q: What is a Collision?
A: A collision happens when two different keys produce the same hash code. Java stores these keys in a linked list (or tree) within the same bucket.
Q: HashMap vs Hashtable?
A: HashMap is unsynchronized, faster, and allows nulls. Hashtable is legacy, synchronized, and forbids nulls. For modern thread-safety, use ConcurrentHashMap.
The Map Interface is the ultimate data retrieval system. By mastering the differences between HashMap, TreeMap, and LinkedHashMap, you can choose the right balance between speed and order. Maps turn complex $O(n)$ search problems into instant $O(1)$ lookups, making them essential for any high-performance Java application.