Map Interface
The Map interface stores key-value pairs. Keys are unique; values can repeat. Map is a separate hierarchy — it does not extend Collection.
Map Hierarchy
Section titled “Map Hierarchy”Map<K,V>├── HashMap<K,V> — hash table, O(1) ops, no ordering├── LinkedHashMap<K,V> — insertion or access order├── SortedMap → NavigableMap│ └── TreeMap<K,V> — red-black tree, sorted keys├── Hashtable<K,V> — synchronized (legacy, avoid)└── ConcurrentMap ├── ConcurrentHashMap — high-performance concurrent map └── ConcurrentSkipListMap — concurrent + sortedImplementation Comparison
Section titled “Implementation Comparison”| HashMap | LinkedHashMap | TreeMap | ConcurrentHashMap | |
|---|---|---|---|---|
| get/put/remove | O(1)* | O(1)* | O(log n) | O(1)* |
| Ordering | None | Insertion/Access | Sorted | None |
| Null keys | 1 allowed | 1 allowed | No | No |
| Null values | Yes | Yes | Yes | No |
| Thread-safe | No | No | No | Yes |
*Average — O(n) worst case from hash collisions
Basic Operations
Section titled “Basic Operations”Map<String, Integer> scores = new HashMap<>();
// Insertscores.put("Alice", 95);scores.put("Bob", 87);
// Retrievescores.get("Alice"); // 95scores.get("Unknown"); // nullscores.getOrDefault("Unknown", 0); // 0
// Checkscores.containsKey("Alice"); // truescores.containsValue(87); // true
// Removescores.remove("Bob"); // 87scores.remove("Alice", 100); // false — value doesn't match
// Sizescores.size();scores.isEmpty();Iteration
Section titled “Iteration”// Over entries (most common)for (Map.Entry<String, Integer> e : map.entrySet()) { System.out.println(e.getKey() + " = " + e.getValue());}
// Over keysfor (String key : map.keySet()) { ... }
// Over valuesfor (Integer val : map.values()) { ... }
// forEach (Java 8+)map.forEach((key, val) -> System.out.println(key + " = " + val));Java 8+ Compute Methods
Section titled “Java 8+ Compute Methods”These eliminate the common “check-then-act” patterns:
// Add only if key is absentmap.putIfAbsent("Alice", 100); // won't overwrite existing 95
// Compute if absent — lazy value creationmap.computeIfAbsent("counts", k -> new ArrayList<>()).add(item);
// Compute if present — update existing valuemap.computeIfPresent("Alice", (k, v) -> v + 5); // 95 → 100
// Merge — combine old and new valuesmap.merge("Alice", 10, Integer::sum); // 100 → 110
// Replacemap.replace("Alice", 110, 120); // only if current value is 110HashMap
Section titled “HashMap”The default choice. Uses hashing for O(1) average-case operations.
Map<String, Integer> map = new HashMap<>(); // capacity 16, load 0.75Map<String, Integer> map = new HashMap<>(100); // pre-sizeMap<String, Integer> map = new HashMap<>(existing); // copyImportant: Keys must have consistent hashCode() and equals(). If you use mutable objects as keys and modify them after insertion, the map breaks silently.
Capacity and load factor: When the number of entries exceeds capacity × loadFactor, the map rehashes into a larger table. Pre-sizing avoids costly rehashing.
LinkedHashMap
Section titled “LinkedHashMap”Same as HashMap but preserves insertion order. Can also be configured for access order (most recently accessed last) — useful for building LRU caches.
// Insertion order (default)Map<String, Integer> map = new LinkedHashMap<>();
// Access order — entries move to end when accessedMap<String, Integer> map = new LinkedHashMap<>(16, 0.75f, true);
// LRU Cache — evict oldest entry when size exceeds limitMap<String, String> lru = new LinkedHashMap<>(16, 0.75f, true) { @Override protected boolean removeEldestEntry(Map.Entry<String, String> eldest) { return size() > 100; }};TreeMap
Section titled “TreeMap”Keeps keys sorted (natural order or via Comparator). Backed by a red-black tree.
TreeMap<Integer, String> map = new TreeMap<>();map.put(5, "five");map.put(2, "two");map.put(8, "eight");// keySet iteration: 2, 5, 8
// Navigable methodsmap.ceilingKey(6); // 8 — smallest key >= 6map.floorKey(6); // 5 — largest key <= 6map.higherKey(5); // 8 — smallest key > 5map.lowerKey(5); // 2 — largest key < 5
// Range viewsmap.subMap(2, true, 8, true); // {2=two, 5=five, 8=eight}map.headMap(5); // {2=two}map.tailMap(5); // {5=five, 8=eight}
map.firstEntry(); // 2=twomap.lastEntry(); // 8=eightImmutable Maps
Section titled “Immutable Maps”// Java 9+ — up to 10 entriesMap<String, Integer> map = Map.of("a", 1, "b", 2, "c", 3);
// Java 9+ — any number of entriesMap<String, Integer> map = Map.ofEntries( Map.entry("a", 1), Map.entry("b", 2), Map.entry("c", 3));
// Unmodifiable wrapperMap<String, Integer> unmod = Collections.unmodifiableMap(mutableMap);When to Use Which
Section titled “When to Use Which”| Scenario | Use |
|---|---|
| General-purpose key-value storage | HashMap |
| Need insertion order | LinkedHashMap |
| Need sorted keys or range queries | TreeMap |
| LRU cache | LinkedHashMap (access-order mode) |
| Thread-safe | ConcurrentHashMap |
| Thread-safe + sorted | ConcurrentSkipListMap |