Ever wanted a HashMap
that remembers the order in which keys were inserted or accessed? That's where LinkedHashMap
steps in. It combines the fast lookup of a HashMap
with predictable iteration order—either insertion order or access order. This makes it ideal for cache implementations, logics that depend on ordering, or LRU policies.
In this tutorial, we’ll break down how LinkedHashMap
works internally, how it's different from HashMap
, and how you can make the most of its two ordering strategies.
Table of Contents
- What is LinkedHashMap?
- Java Syntax and Constructors
- Insertion Order vs Access Order
- Internal Working and Data Structure
- Performance and Big-O Complexity
- Real-World Use Cases
- Java Version Enhancements (Java 8–21)
- Functional Programming Support (Java 8+)
- Comparisons: LinkedHashMap vs HashMap vs TreeMap
- Pros and Cons
- Anti-patterns and Common Pitfalls
- Refactoring with LinkedHashMap
- Best Practices
- 📌 What's New in Java [version]?
- Conclusion and Key Takeaways
- FAQ – 10 Expert-Level Questions
What is LinkedHashMap?
LinkedHashMap
is a subclass of HashMap
that maintains a doubly-linked list running through all of its entries. This allows predictable iteration order: either by insertion or by access.
Java Syntax and Constructors
LinkedHashMap<String, Integer> map = new LinkedHashMap<>();
To enable access-order (useful for caches):
LinkedHashMap<String, Integer> lruMap =
new LinkedHashMap<>(16, 0.75f, true);
Insertion Order vs Access Order
Mode | Description |
---|---|
Insertion Order | Iteration reflects the order in which keys were inserted |
Access Order | Iteration reflects the order in which keys were last accessed (get/put) |
Example
LinkedHashMap<String, String> map = new LinkedHashMap<>(16, 0.75f, true);
map.put("A", "Apple");
map.put("B", "Banana");
map.get("A"); // "A" moves to end
map.forEach((k, v) -> System.out.println(k)); // Output: B A
Internal Working and Data Structure
LinkedHashMap
extends HashMap
but overrides internal methods to maintain a linked list of entries.
static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after; // Doubly-linked list pointers
}
- Maintains head and tail pointers
- Updates on
put()
and optionally onget()
(if accessOrder is true)
Performance and Big-O Complexity
Operation | Time Complexity |
---|---|
get/put/remove | O(1) |
iteration | O(n) |
reordering | O(1) per access |
Real-World Use Cases
- Implementing LRU Cache
- Tracking recently accessed data
- Maintaining predictable iteration for logs or snapshots
- Ordered form field validations
Java Version Enhancements
Java 8
forEach
,computeIfAbsent
, lambdas- Functional processing of entries
Java 9+
Map.of()
creates immutable maps (not LinkedHashMap though)- APIs remain stable
Java 21
- Minor performance optimizations
Functional Programming Support
LinkedHashMap<String, Integer> scores = new LinkedHashMap<>();
scores.put("Alice", 90);
scores.put("Bob", 85);
scores.entrySet()
.stream()
.filter(e -> e.getValue() > 80)
.forEach(e -> System.out.println(e.getKey()));
Comparisons
Feature | HashMap | LinkedHashMap | TreeMap |
---|---|---|---|
Order | Unordered | Insertion or Access | Sorted (by key) |
Null keys | 1 allowed | 1 allowed | Not allowed |
Performance | Fastest | Slightly slower | Slowest (O log n) |
Pros and Cons
✅ Pros
- Predictable order
- Fast access like HashMap
- Ideal for LRU cache
❌ Cons
- Slight overhead due to linked list
- No concurrent access (not thread-safe)
Anti-patterns and Common Pitfalls
❌ Misusing accessOrder
new LinkedHashMap<>(16, 0.75f, true); // Access-order
// But forgetting that get() affects order
❌ Large LinkedHashMaps without trimming
Use overridden removeEldestEntry()
:
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > MAX_ENTRIES;
}
Refactoring with LinkedHashMap
Replace unordered HashMaps in logging logic or caching with LinkedHashMap for predictable behavior.
Before:
Map<String, String> cache = new HashMap<>();
After:
Map<String, String> cache = new LinkedHashMap<>(16, 0.75f, true);
Best Practices
- Always define capacity if size is predictable
- For LRU cache, override
removeEldestEntry()
- Use accessOrder = true only when needed
- Avoid modifying during iteration
📌 What's New in Java [version]?
Java 8
- Lambdas and
forEach()
support computeIfAbsent()
,getOrDefault()
Java 9
- Immutable maps via
Map.of()
(not LinkedHashMap-specific)
Java 10
var
for local variable type inference
Java 21
- Minor GC and access-order optimization improvements
Conclusion and Key Takeaways
LinkedHashMap
provides ordered access with O(1) performance- Access order is ideal for cache use-cases
- Minimal overhead with maximum predictability
- Java 8+ features simplify usage further
FAQ – 10 Expert-Level Questions
1. Does LinkedHashMap preserve order?
Yes, based on insertion or access order.
2. Is LinkedHashMap thread-safe?
No. Use Collections.synchronizedMap()
or ConcurrentHashMap
.
3. What’s the difference between access and insertion order?
Access order moves entries to the end on get()
/put()
; insertion order doesn’t.
4. Can you convert HashMap to LinkedHashMap?
Yes, via constructor or streams.
5. How do you make an LRU cache?
Set accessOrder = true and override removeEldestEntry()
.
6. Can you use null keys and values?
Yes, one null key and multiple null values.
7. Is iteration order guaranteed?
Yes. That’s the primary benefit of LinkedHashMap.
8. What is removeEldestEntry?
A protected method to remove the oldest entry upon new insertion.
9. When is LinkedHashMap preferred over HashMap?
When you need ordering with fast access.
10. Is it faster than TreeMap?
Yes. LinkedHashMap has O(1) access while TreeMap has O(log n).