-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLinkedHashMapDemo.java
More file actions
125 lines (113 loc) · 5.04 KB
/
Copy pathLinkedHashMapDemo.java
File metadata and controls
125 lines (113 loc) · 5.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package Phase5_CollectionsLambdasStreams.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* java.util.LinkedHashMap<K, V> - HashMap with Predictable Order
* --------------------------------------------------------------
* LinkedHashMap extends HashMap. Internally it weaves a doubly-linked list
* through its entries so iteration follows a predictable order. The hash-
* table operations remain O(1); the linked list just adds a few pointers.
* <p>
*
* Two Order Modes
* ---------------
* 1. INSERTION ORDER (default)
* Entries iterated in the order put() first added them.
* <p>
*
* 2. ACCESS ORDER new LinkedHashMap<>(16, 0.75f, true)
* Every get() / put() moves that entry to the END. Perfect for LRU.
* <p>
*
* Why It Exists
* -------------
* - You want O(1) lookup AND a deterministic iteration order
* (insertion or access).
* - You want to build a simple LRU CACHE by overriding removeEldestEntry.
* - You want JSON / config dumps to iterate in the order keys were added.
* <p>
*
* Big-O
* -----
* put / get / remove / containsKey O(1) (same as HashMap)
* iteration O(size)
* <p>
*
* Constructors
* ------------
* new LinkedHashMap<>()
* new LinkedHashMap<>(int initialCapacity)
* new LinkedHashMap<>(int initialCapacity, float loadFactor)
* new LinkedHashMap<>(int initialCapacity, float loadFactor, boolean accessOrder)
* new LinkedHashMap<>(Map<? extends K, ? extends V> m)
* <p>
*
* Java 21 - SequencedMap
* ----------------------
* LinkedHashMap implements the new SequencedMap interface (Java 21):
* firstEntry, lastEntry, putFirst, putLast, pollFirstEntry, pollLastEntry,
* reversed(). See Basics/ModernJava/SequencedCollections.java.
*/
public class LinkedHashMapDemo {
public static void main(String[] args) {
section("1) Insertion order - iteration is deterministic");
LinkedHashMap<String, Integer> m = new LinkedHashMap<>();
m.put("third", 3);
m.put("first", 1);
m.put("second", 2);
for (var e : m.entrySet()) {
System.out.println(" " + e.getKey() + " -> " + e.getValue());
}
section("2) Updating a key does NOT change its insertion position");
LinkedHashMap<String, Integer> u = new LinkedHashMap<>();
u.put("a", 1); u.put("b", 2); u.put("c", 3);
u.put("a", 99); // value changes; order unchanged
System.out.println("after update : " + u);
section("3) Access-order mode (the LRU foundation)");
LinkedHashMap<String, Integer> lru = new LinkedHashMap<>(16, 0.75f, true);
lru.put("a", 1); lru.put("b", 2); lru.put("c", 3);
lru.get("a"); // accessing 'a' moves it to the end
lru.get("b"); // and now 'b' is at the end
System.out.println("after gets : " + lru); // c, a, b
section("4) A simple LRU cache built on LinkedHashMap");
// We override removeEldestEntry - the JDK calls this on every put
// and removes the eldest entry when we return true.
final int CAPACITY = 3;
LinkedHashMap<String, Integer> cache = new LinkedHashMap<>(16, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<String, Integer> eldest) {
return size() > CAPACITY;
}
};
cache.put("a", 1);
cache.put("b", 2);
cache.put("c", 3);
cache.put("d", 4); // evicts the eldest 'a'
System.out.println("cache now : " + cache);
cache.get("b"); // 'b' becomes most recently used
cache.put("e", 5); // evicts the eldest, which is now 'c'
System.out.println("after touches: " + cache);
section("5) All HashMap methods still work");
LinkedHashMap<String, Integer> lhm = new LinkedHashMap<>(Map.of("x", 1, "y", 2, "z", 3));
lhm.merge("x", 10, Integer::sum);
lhm.computeIfAbsent("w", k -> 4);
System.out.println("lhm = " + lhm);
section("6) Java 21 SequencedMap - first/last/reversed (via reflection so it compiles on 17)");
try {
var firstM = LinkedHashMap.class.getMethod("firstEntry");
var lastM = LinkedHashMap.class.getMethod("lastEntry");
var revM = LinkedHashMap.class.getMethod("reversed");
System.out.println("firstEntry = " + firstM.invoke(lhm));
System.out.println("lastEntry = " + lastM.invoke(lhm));
System.out.println("reversed = " + revM.invoke(lhm));
} catch (NoSuchMethodException e) {
System.out.println("(Java 21+ needed for SequencedMap - skipped)");
} catch (Exception e) {
System.out.println("reflection error: " + e.getMessage());
}
// OUTPUT (matches inline comments)
}
private static void section(String title) {
System.out.println("\n====== " + title + " ======");
}
}