Java Map Interface Explained: HashMap, LinkedHashMap, and TreeMap
Learn the Java Map interface with HashMap, LinkedHashMap, TreeMap, ConcurrentHashMap, key-value lookup, ordering, performance, and real-world examples.
Last reviewed: August 2026
🔍 What Is It?
Map Interface
java.util.Map (does NOT extend Collection):
- →put(K key, V value) — add or replace entry
- →get(Object key) — retrieve by key (returns null if missing)
- →getOrDefault(Object key, V defaultValue) — safe get
- →containsKey(Object key) — O(1) for HashMap
- →remove(Object key) — remove entry
- →keySet() — Set of all keys
- →values() — Collection of all values
- →entrySet() — Set<Map.Entry<K,V>> for iterating pairs
- →putIfAbsent(K key, V value) — only puts if key not present
- →computeIfAbsent(K key, Function) — compute value if absent
- →merge(K key, V value, BiFunction) — merge with existing value
Key Implementations:
- →HashMap — hash table; O(1) average; no ordering
- →LinkedHashMap — HashMap + insertion order; O(1); useful for LRU cache
- →TreeMap — Red-Black tree; O(log n); keys always sorted
- →ConcurrentHashMap — thread-safe HashMap; fine-grained locking
- →EnumMap — specialized for enum keys; array-backed; very fast
- →Map.of() — immutable map (Java 9+); max 10 entries
- →Map.copyOf() — immutable copy of existing map
🎯 Why Do We Need It?
Maps are the most versatile data structure in Java:
- →Fast lookup — O(1) find by key (vs O(n) for List)
- →Grouping — group orders by customer, products by category
- →Caching — store computed results keyed by input
- →Configuration — property name to value
- →Counting — word frequency, event counts
- →Index — build an in-memory index for fast search
🏗️ What Happens in Real Projects?
Maps appear in virtually every Java service:
// Cache / lookup table
Map<String, User> userCache = new HashMap<>();
User user = userCache.computeIfAbsent(userId, id -> userRepo.findById(id));
// Grouping (replaced by Collectors.groupingBy in streams)
Map<String, List<Order>> ordersByCustomer = orders.stream()
.collect(Collectors.groupingBy(Order::getCustomerId));
// Counting
Map<String, Long> countByStatus = orders.stream()
.collect(Collectors.groupingBy(
o -> o.getStatus().name(),
Collectors.counting()
));⚙️ How It Works
HashMap Internals:
- →Array of "buckets" (linked lists or trees)
- →put(key, value): compute hashCode, find bucket, check for existing key with equals(), store
- →get(key): compute hashCode, find bucket, find entry with equals()
- →Java 8+: buckets with 8+ entries convert to balanced trees (O(log n) worst case)
- →Default initial capacity: 16; load factor: 0.75 (resize when 75% full)
- →Resizing doubles the array and rehashes all entries — O(n) operation
Good hash function distributes keys evenly across buckets. Poor hash functions (many collisions) degrade HashMap to O(n).
💻 Example
Map Patterns Every Developer Uses — The Map operations and patterns you will use in every enterprise project.
🤔 Common Confusions
❓ What happens when HashMap has many collisions?
If many keys hash to the same bucket, performance degrades. Before Java 8, buckets were linked lists — worst case O(n). Java 8+ converts buckets with 8+ entries to balanced trees — worst case O(log n). The real fix is a good hashCode() implementation that distributes keys evenly. String and Integer have excellent hash functions; custom objects need careful implementation.
❓ What is the difference between HashMap and Hashtable?
Hashtable is the legacy synchronized HashMap from Java 1.0. It is slower (all methods synchronized), does not allow null keys or values, and is considered obsolete. Use HashMap for single-threaded code and ConcurrentHashMap for thread-safe concurrent access. Never use Hashtable in new code.
❓ Why does Map not extend Collection?
Map represents a mapping (key to value) — it is fundamentally different from a Collection (sequence of elements). A Map entry is a key-value pair, not a single element. Forcing Map into the Collection hierarchy would require deciding: does size() return key count, value count, or entry count? The designers kept them separate for clarity.
🚨 Common Production Issues
HashMap in concurrent code — HashMap is not thread-safe. Concurrent modification can cause infinite loops (Java 7) or data corruption. Use ConcurrentHashMap for concurrent access.
Memory leak with computeIfAbsent for caching — unbounded maps grow forever. Use a cache library (Caffeine, Guava Cache) with eviction policies instead.
HashMap initial capacity — if you know you will store 10,000 entries, initialize with new HashMap<>(16384) (next power of 2 above 10000/0.75) to avoid resizing.
✅ Best Practices
Use HashMap as default; LinkedHashMap when order matters; TreeMap when sorted iteration is needed.
Use getOrDefault() instead of get() + null check.
Use computeIfAbsent() for lazy initialization patterns (e.g., building a map of lists).
Use merge() for counting and accumulation patterns.
Use ConcurrentHashMap for thread-safe maps — never synchronize a HashMap manually.
For enum keys, use EnumMap — it is faster than HashMap for enum types.
🏛️ Architect's Note
Maps are the foundation of most caching strategies. However, in-memory HashMaps are not suitable for distributed caching (multiple instances do not share state). For production caching, use Redis (via Spring Cache), Caffeine (local cache with eviction), or Hazelcast (distributed). The Map interface is the same — swap the implementation without changing business code.
💬 Frequently Asked Questions
🎯 Key Takeaways
🔗 Related Topics
🎯 Practice this topic in interviews
Core Java Interview Prep
Practice interview questions that connect directly to this technology track.
↗ Where this topic fits
Core Java Technology Guide
Return to the Core Java learning hub.
Backend Engineer Career Path
A structured journey through Core Java, Spring Boot, production backend engineering, and interview preparation.
Full Stack Java Developer Career Path
A guided route through frontend foundations, Java backend engineering, delivery workflows, and interview readiness.
Sources
Sources / References
Use these Core Java references to verify the concept in official docs and continue into the most relevant SplashRide pages.
Official documentation
Related SplashRide pages
SplashRide Core Java learning path
Browse the full Core Java topic collection and learning order on SplashRide.
Core Java Interview Prep
Practice Core Java interview questions and scenario-based answers.
Backend Engineer Career Path
A structured journey through Core Java, Spring Boot, production backend engineering, and interview preparation.
Full Stack Java Developer Career Path
A guided route through frontend foundations, Java backend engineering, delivery workflows, and interview readiness.
List
The List interface — ordered, indexed, allows duplicates. When to use ArrayList vs LinkedList, and the patterns senior developers rely on.
Set
The Set interface — no duplicates, fast membership testing. HashSet, LinkedHashSet, TreeSet — when to use each.