LinkedHashMap in Java – Complete Guide with Examples
LinkedHashMap is a HashMap that remembers order. By default it returns entries in the order they were inserted; optionally it can order them by most recent access, which makes it the classic building block for an LRU cache.
It lives in java.util, extends HashMap, and has been available since JDK 1.4. You get HashMap's O(1) speed plus predictable iteration, at the cost of a little extra memory.
1. What Is a LinkedHashMap?
Think of a restaurant waiting list: each party's name (key) is linked to the party size (value), and the list keeps the order in which people arrived. A LinkedHashMap is a fast lookup table that also keeps such a list.
- All HashMap features: unique keys, O(1) operations, one
nullkey andnullvalues. - Insertion order by default; updating an existing key does not move it.
- Access order on request: every read or write moves the entry to the end.
removeEldestEntry()hook to evict old entries automatically.- A SequencedMap since Java 21, with
firstEntry(),lastEntry(),putFirst()andreversed(). - Not synchronized.
2. Class Hierarchy and Declaration
public class LinkedHashMap<K, V> extends HashMap<K, V>
implements SequencedMap<K, V> // Java 21+ (Map before)
3. Insertion Order in Action
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
public class LinkedHashMapQuickStart {
public static void main(String[] args) {
String[] steps = {"wake", "exercise", "breakfast", "commute", "work"};
Map<String, Integer> hash = new HashMap<>();
Map<String, Integer> linked = new LinkedHashMap<>();
for (int i = 0; i < steps.length; i++) {
hash.put(steps[i], i + 1);
linked.put(steps[i], i + 1);
}
System.out.println("HashMap: " + hash);
System.out.println("LinkedHashMap: " + linked);
linked.put("wake", 0); // updating a key keeps its position
System.out.println("After update: " + linked);
}
}
HashMap: {wake=1, work=5, exercise=2, breakfast=3, commute=4}
LinkedHashMap: {wake=1, exercise=2, breakfast=3, commute=4, work=5}
After update: {wake=0, exercise=2, breakfast=3, commute=4, work=5}
The HashMap scrambles the morning routine; the LinkedHashMap keeps it in order. Updating "wake" changed its value but not its position.
4. Constructors
| Constructor | What it does |
|---|---|
LinkedHashMap() | Empty map, insertion order, capacity 16, load factor 0.75. |
LinkedHashMap(int initialCapacity) | Empty map with the given capacity. |
LinkedHashMap(int initialCapacity, float loadFactor) | Empty map with the given capacity and load factor. |
LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) | true for access order, false for insertion order. |
LinkedHashMap(Map<? extends K, ? extends V> m) | A map with the entries of m, in m's iteration order. |
Java 19 added LinkedHashMap.newLinkedHashMap(int numMappings) for pre-sizing.
5. Access Order
With accessOrder = true, every get(), put() (and getOrDefault(), compute(), merge() …) on a key moves that entry to the end. The first entry is then always the least recently used one.
import java.util.LinkedHashMap;
import java.util.Map;
public class AccessOrderDemo {
public static void main(String[] args) {
// third argument true = access order (least recently used first)
Map<String, String> pages = new LinkedHashMap<>(16, 0.75f, true);
pages.put("home", "...");
pages.put("about", "...");
pages.put("blog", "...");
System.out.println("Start: " + pages.keySet());
pages.get("home"); // reading moves "home" to the end
System.out.println("After get(home): " + pages.keySet());
pages.put("about", "updated"); // writing also counts as access
System.out.println("After put(about): " + pages.keySet());
}
}
Start: [home, about, blog] After get(home): [about, blog, home] After put(about): [blog, home, about]
get() changes the map's structure. Calling get() while iterating over the map throws ConcurrentModificationException.6. Building an LRU Cache
An LRU (Least Recently Used) cache keeps a fixed number of entries and throws away the one that has not been used for the longest time. LinkedHashMap does almost all the work: use access order and override removeEldestEntry(), which is called after every insert.
import java.util.LinkedHashMap;
import java.util.Map;
public class LruCache<K, V> extends LinkedHashMap<K, V> {
private final int capacity;
public LruCache(int capacity) {
super(16, 0.75f, true); // access order
this.capacity = capacity;
}
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > capacity; // evict when over capacity
}
public static void main(String[] args) {
LruCache<Integer, String> cache = new LruCache<>(3);
cache.put(1, "one");
cache.put(2, "two");
cache.put(3, "three");
cache.get(1); // 1 is now most recently used
cache.put(4, "four"); // evicts 2, the least recently used
System.out.println("Cache: " + cache.keySet());
System.out.println("Contains 2? " + cache.containsKey(2));
}
}
Cache: [3, 1, 4] Contains 2? false
Key 2 was evicted because key 1 had been read more recently. For production caches with expiry, statistics or concurrency, a library such as Caffeine is a better choice; this pattern is perfect for small, single-threaded caches and for interviews.
7. How LinkedHashMap Works Internally
LinkedHashMap reuses all of HashMap's hashing logic. Its entries are a subclass of HashMap's nodes with two extra links, before and after, which form a doubly linked list through all entries. The map also keeps head and tail references.
- put (new key): HashMap stores the node in its bucket, and the node is linked at the tail.
- remove: the node is removed from its bucket and unlinked from the list.
- access (access-order mode): the node is moved to the tail.
- iteration: walks the list from head to tail, so it is O(n) regardless of capacity.
- after insert:
removeEldestEntry(head)is called; if it returnstrue, the head is removed.
8. Java 21: SequencedMap Methods
Since Java 21, LinkedHashMap implements SequencedMap, giving direct access to both ends:
import java.util.LinkedHashMap;
public class SequencedMapDemo {
public static void main(String[] args) {
LinkedHashMap<String, Integer> queue = new LinkedHashMap<>();
queue.put("Asha", 1);
queue.put("Ravi", 2);
queue.put("Meera", 3);
// Java 21 SequencedMap methods
System.out.println("firstEntry(): " + queue.firstEntry());
System.out.println("lastEntry(): " + queue.lastEntry());
queue.putFirst("VIP", 0); // insert at the front
System.out.println("After putFirst: " + queue);
System.out.println("pollFirstEntry(): " + queue.pollFirstEntry() + " -> " + queue);
System.out.println("reversed(): " + queue.reversed());
}
}
firstEntry(): Asha=1
lastEntry(): Meera=3
After putFirst: {VIP=0, Asha=1, Ravi=2, Meera=3}
pollFirstEntry(): VIP=0 -> {Asha=1, Ravi=2, Meera=3}
reversed(): {Meera=3, Ravi=2, Asha=1}
putFirst() and putLast() also move an existing key to that end. sequencedKeySet(), sequencedValues() and sequencedEntrySet() return ordered views.
9. Practical Example: Keeping a Sorted Result
When you sort map entries with a stream, collect them into a LinkedHashMap; a plain HashMap would lose the order immediately.
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
public class SortByValue {
public static void main(String[] args) {
Map<String, Integer> runs = Map.of("Rohit", 45, "Virat", 82, "Gill", 17, "Rahul", 60);
Map<String, Integer> ranked = runs.entrySet().stream()
.sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(a, b) -> a, LinkedHashMap::new)); // LinkedHashMap keeps the sort
System.out.println("Top scorers: " + ranked);
}
}
Top scorers: {Virat=82, Rahul=60, Rohit=45, Gill=17}
10. Common Methods
| Method | Description |
|---|---|
put, get, remove, containsKey | Same as HashMap, O(1). In access-order mode, get and put move the entry to the end. |
keySet(), values(), entrySet() | Views that iterate in the map's order. |
removeEldestEntry(Map.Entry eldest) | Protected hook; return true to remove the eldest entry after an insert. |
firstEntry(), lastEntry() | First or last entry (Java 21). |
pollFirstEntry(), pollLastEntry() | Remove and return the first or last entry (Java 21). |
putFirst(k, v), putLast(k, v) | Insert or move an entry to an end (Java 21). |
reversed() | Reverse-ordered view (Java 21). |
11. HashMap vs LinkedHashMap vs TreeMap
| Feature | HashMap | LinkedHashMap | TreeMap |
|---|---|---|---|
| Order | None | Insertion or access | Sorted by key |
| get / put | O(1) | O(1) | O(log n) |
| Iteration | O(n + capacity) | O(n) | O(n) |
| null key | One | One | No |
| Memory | Lowest | Higher (two links per entry) | Higher (tree nodes) |
| Special feature | – | LRU via removeEldestEntry | Range and nearest-key queries |
12. When to Use LinkedHashMap
- The order of entries is visible to users, logs, JSON output or tests.
- You build a simple LRU or FIFO cache.
- You need to keep the result of a sort or a grouping in order.
- You want repeatable iteration order without paying for sorting.
13. Thread Safety
LinkedHashMap is not synchronized. Wrap it with Collections.synchronizedMap(new LinkedHashMap<>(...)) and synchronize on the wrapper while iterating. There is no concurrent LinkedHashMap in the JDK; for concurrent caches, use a dedicated library.
14. Summary
- LinkedHashMap is a HashMap with a doubly linked list through its entries.
- It keeps insertion order by default, or access order with
accessOrder = true. - Overriding
removeEldestEntry()turns it into an LRU or FIFO cache. - Operations are O(1); iteration is O(n) and predictable.
- Java 21 added first/last entry,
putFirst/putLastandreversed().
Related Tutorials
Reference: Java SE 21 API: java.util.LinkedHashMap
Frequently Asked Questions (FAQ)
Q1. What is a LinkedHashMap in Java?
LinkedHashMap is a class in java.util that extends HashMap and keeps its entries in a predictable order: insertion order by default, or access order if requested. It offers HashMap's O(1) operations.
Q2. How does LinkedHashMap maintain order?
Each entry has before and after links that form a doubly linked list across all entries. New entries are added at the tail, and iteration follows the list from head to tail.
Q3. What is the difference between insertion order and access order?
Insertion order keeps entries in the order their keys were first added. Access order moves an entry to the end every time it is read or written, so the first entry is the least recently used.
Q4. Does updating a value change the order in a LinkedHashMap?
Not in insertion-order mode: re-putting an existing key keeps its position. In access-order mode, the update counts as an access and moves the entry to the end.
Q5. How do I implement an LRU cache with LinkedHashMap?
Create it with accessOrder = true and override removeEldestEntry() to return size() > capacity. After each insert, the least recently used entry is removed automatically.
Q6. What is removeEldestEntry()?
A protected method that LinkedHashMap calls after every put or putAll, passing the eldest entry. The default returns false. Override it to return true when the eldest entry should be removed, for example when the map is over a size limit.
Q7. What is the difference between HashMap and LinkedHashMap?
Both are O(1) hash tables. HashMap has no guaranteed order; LinkedHashMap keeps insertion or access order, iterates in O(n), and supports LRU eviction, but uses a bit more memory per entry.
Q8. Is LinkedHashMap slower than HashMap?
Slightly, for put and remove, because the links must be updated. Lookups are just as fast, and iteration can be faster for maps with a large capacity and few entries.
Q9. Does LinkedHashMap allow null keys and values?
Yes, one null key and any number of null values, just like HashMap.
Q10. Is LinkedHashMap thread-safe?
No. Wrap it with Collections.synchronizedMap(). In access-order mode, remember that even get() modifies the map, so every call must be synchronized.
Q11. Why does calling get() during iteration throw ConcurrentModificationException?
Only in access-order mode: get() moves the entry, which is a structural change, so the fail-fast iterator stops. In insertion-order mode, get() is safe during iteration.
Q12. How do I get the first or last entry of a LinkedHashMap?
On Java 21 and later, use firstEntry() and lastEntry(). On older versions, use map.entrySet().iterator().next() for the first entry and iterate to the end for the last.
Q13. What is the default capacity and load factor of LinkedHashMap?
16 and 0.75, the same as HashMap, with the same resizing rules.
Q14. How do I sort a map by value and keep the order?
Sort the entries with a stream and collect them into a LinkedHashMap using Collectors.toMap(..., (a, b) -> a, LinkedHashMap::new), as shown in the example above.
Q15. Can LinkedHashMap be used as a FIFO cache?
Yes. Keep the default insertion order and override removeEldestEntry(). The oldest inserted entry is evicted, regardless of how often it was read.
Q16. What is the time complexity of LinkedHashMap operations?
put, get, remove and containsKey are O(1) on average. Iteration is O(n). containsValue is O(n).
Q17. When was LinkedHashMap introduced?
In JDK 1.4. Java 19 added newLinkedHashMap(), and Java 21 made it a SequencedMap.
Q18. What is the difference between LinkedHashMap and TreeMap?
LinkedHashMap keeps insertion or access order with O(1) operations. TreeMap keeps keys sorted with O(log n) operations and provides navigation methods such as floorKey() and subMap().
Q19. Does LinkedHashSet use LinkedHashMap?
Yes. LinkedHashSet is backed by a LinkedHashMap in insertion-order mode, with its elements stored as keys.
Q20. Does containsKey() count as an access in access-order mode?
No. Only methods that read or write a mapping, such as get, getOrDefault, put, putIfAbsent, compute and merge, move the entry. containsKey() and iteration through views do not.