Java LinkedHashMap
HashMap with predictable insertion-order iteration
🔗 What is LinkedHashMap?
LinkedHashMap combines HashMap's fast performance with predictable iteration order. It maintains insertion order using a doubly-linked list, perfect for ordered key-value storage needs.
// LinkedHashMap maintains insertion order
LinkedHashMap<String, Integer> map = new LinkedHashMap<>();
map.put("Third", 3);
map.put("First", 1);
map.put("Second", 2);
System.out.println(map); // {Third=3, First=1, Second=2}
LinkedHashMap Key Features
Insertion Order
Maintains the order elements were added
LinkedHashMap<String, String> colors = new LinkedHashMap<>();
colors.put("R", "Red");
colors.put("G", "Green");
colors.put("B", "Blue");
// Always iterates: R, G, B
Fast Performance
Same O(1) performance as HashMap
LinkedHashMap<String, Integer> cache = new LinkedHashMap<>();
cache.put("key1", 100); // O(1)
Integer val = cache.get("key1"); // O(1)
cache.remove("key1"); // O(1)
Access Order
Optional access-order iteration mode
// Access-order LinkedHashMap (LRU cache)
LinkedHashMap<String, Integer> lru =
new LinkedHashMap<>(16, 0.75f, true);
lru.put("A", 1);
lru.put("B", 2);
lru.get("A"); // A moves to end
LRU Cache
Perfect for implementing LRU caches
class LRUCache<K,V> extends LinkedHashMap<K,V> {
private int maxSize;
LRUCache(int maxSize) {
super(16, 0.75f, true);
this.maxSize = maxSize;
}
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
return size() > maxSize;
}
}
🔹 Creating and Using LinkedHashMap
Basic LinkedHashMap operations with order preservation:
import java.util.*;
public class LinkedHashMapExample {
public static void main(String[] args) {
// Create LinkedHashMap
LinkedHashMap<String, String> userProfiles = new LinkedHashMap<>();
// Add users in specific order
userProfiles.put("user001", "Alice Johnson");
userProfiles.put("user003", "Charlie Brown");
userProfiles.put("user002", "Bob Smith");
userProfiles.put("user004", "Diana Prince");
// Iteration maintains insertion order
System.out.println("User profiles (insertion order):");
for (Map.Entry<String, String> entry : userProfiles.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// Update existing user (order unchanged)
userProfiles.put("user002", "Robert Smith");
// Add new user (goes to end)
userProfiles.put("user005", "Eve Wilson");
System.out.println("\nAfter updates:");
userProfiles.forEach((id, name) ->
System.out.println(id + ": " + name));
// Compare with HashMap (random order)
HashMap<String, String> hashMap = new HashMap<>(userProfiles);
System.out.println("\nSame data in HashMap (random order):");
hashMap.forEach((id, name) ->
System.out.println(id + ": " + name));
}
}
Output:
User profiles (insertion order):
user001: Alice Johnson
user003: Charlie Brown
user002: Bob Smith
user004: Diana Prince
After updates:
user001: Alice Johnson
user003: Charlie Brown
user002: Robert Smith
user004: Diana Prince
user005: Eve Wilson
🔹 Access-Order LinkedHashMap
Using access-order mode for LRU-style behavior:
// Create access-order LinkedHashMap
LinkedHashMap<String, String> accessOrderMap = new LinkedHashMap<>(16, 0.75f, true);
// Add some data
accessOrderMap.put("page1", "Home Page");
accessOrderMap.put("page2", "About Page");
accessOrderMap.put("page3", "Contact Page");
accessOrderMap.put("page4", "Products Page");
System.out.println("Initial order:");
accessOrderMap.forEach((key, value) -> System.out.println(key + ": " + value));
// Access some pages (moves them to end)
accessOrderMap.get("page2"); // About Page accessed
accessOrderMap.get("page1"); // Home Page accessed
System.out.println("\nAfter accessing page2 and page1:");
accessOrderMap.forEach((key, value) -> System.out.println(key + ": " + value));
// Update a page (moves to end)
accessOrderMap.put("page3", "Updated Contact Page");
System.out.println("\nAfter updating page3:");
accessOrderMap.forEach((key, value) -> System.out.println(key + ": " + value));
// Demonstrate LRU behavior
class SimpleLRUCache<K, V> extends LinkedHashMap<K, V> {
private final int maxSize;
public SimpleLRUCache(int maxSize) {
super(16, 0.75f, true); // access-order = true
this.maxSize = maxSize;
}
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > maxSize;
}
}
// Use LRU cache
SimpleLRUCache<String, String> cache = new SimpleLRUCache<>(3);
cache.put("A", "Value A");
cache.put("B", "Value B");
cache.put("C", "Value C");
System.out.println("\nLRU Cache after adding A, B, C: " + cache);
cache.get("A"); // Access A (moves to end)
cache.put("D", "Value D"); // Should remove B (least recently used)
System.out.println("After accessing A and adding D: " + cache);
Output:
Initial order:
page1: Home Page
page2: About Page
page3: Contact Page
page4: Products Page
After accessing page2 and page1:
page3: Contact Page
page4: Products Page
page2: About Page
page1: Home Page
LRU Cache after adding A, B, C: {A=Value A, B=Value B, C=Value C}
After accessing A and adding D: {C=Value C, A=Value A, D=Value D}
🔹 LinkedHashMap vs HashMap vs TreeMap
Comparison of different Map implementations:
// Demonstrate differences between Map implementations
String[] keys = {"Zebra", "Apple", "Banana", "Cherry"};
int[] values = {4, 1, 2, 3};
// HashMap - No guaranteed order
HashMap<String, Integer> hashMap = new HashMap<>();
for (int i = 0; i < keys.length; i++) {
hashMap.put(keys[i], values[i]);
}
System.out.println("HashMap (random order): " + hashMap);
// LinkedHashMap - Insertion order
LinkedHashMap<String, Integer> linkedHashMap = new LinkedHashMap<>();
for (int i = 0; i < keys.length; i++) {
linkedHashMap.put(keys[i], values[i]);
}
System.out.println("LinkedHashMap (insertion order): " + linkedHashMap);
// TreeMap - Sorted order
TreeMap<String, Integer> treeMap = new TreeMap<>();
for (int i = 0; i < keys.length; i++) {
treeMap.put(keys[i], values[i]);
}
System.out.println("TreeMap (sorted order): " + treeMap);
// Performance comparison
System.out.println("\nPerformance Characteristics:");
System.out.println("HashMap: O(1) get/put, no order guarantee");
System.out.println("LinkedHashMap: O(1) get/put, maintains insertion order");
System.out.println("TreeMap: O(log n) get/put, maintains sorted order");
// Memory usage
System.out.println("\nMemory Usage:");
System.out.println("HashMap: Lowest memory usage");
System.out.println("LinkedHashMap: Extra memory for linked list pointers");
System.out.println("TreeMap: Extra memory for tree structure");
Output:
HashMap (random order): {Apple=1, Cherry=3, Zebra=4, Banana=2}
LinkedHashMap (insertion order): {Zebra=4, Apple=1, Banana=2, Cherry=3}
TreeMap (sorted order): {Apple=1, Banana=2, Cherry=3, Zebra=4}
Performance Characteristics:
HashMap: O(1) get/put, no order guarantee
LinkedHashMap: O(1) get/put, maintains insertion order
TreeMap: O(log n) get/put, maintains sorted order