I am a little confused about how to build a LRU cache by using LinkedHashMap (How would you implement an LRU cache in Java 6?), and I want to make sure I understand how it work internally behind the scene.
Lets say I define a class LRUMap that extends the LinkedHashMap and override the removeEldestEntry(final Map.Entry<A, B> eldest)
just like the way it is.
Then I construct the data structure and insert 4 items into the map
LRUMap<String,String> map = new LRUMap<String,String>(3); //capacity 3
map.put("a", "a");
map.put("b", "b");
map.put("c", "c");
map.put("d", "d");
and interally LinkedHashMap
uses an Entry object
called header
as a starting node to link with all the items that you add to the map. So in this case it will be
[header] -> ["a"] -> ["b"] -> ["c"] -> ["d"] -> [header]
The header Entry object is both the start and the end of the doubly linked list since header.before = header.after = header when it initially constructs.
And lets say the map reaches the maximum Entries (3 items) that I want it to be, and from
Entry<K,V> eldest = header.after;
if (removeEldestEntry(eldest)) {
removeEntryForKey(eldest.key);
}
.....
So does that mean it will remove ["a"] first ?
And when we call get(Object key)
does it rearrange the list order where it puts that key (lets say "b") before the header node, so it becomes
[header] -> ["c"] -> ["d"] -> ["b"] -> [header]
Just want to clarify that.
An LRU cache is built by combining two data structures: a doubly linked list and a hash map.
LinkedHashMap is the data structure used to store the key-value pairs like HashMap but it guarantees the order of insertion(unlike the HashMap). So the elements are stored in the order of their insertion.
Optimized Approach: The key to solve this problem is using a double linked list which enables us to quickly move nodes. The LRU cache is a hash map of keys and double linked nodes. The hash map makes the time of get() to be O(1). The list of double linked nodes make the nodes adding/removal operations O(1).
<"a", "a">
will be removed first :-)Maybe; LinkedHashMap
by default uses insertion-order, not access-order...
straight from the specification:
Hash table and linked list implementation of the
Map
interface, with predictable iteration order. This implementation differs fromHashMap
in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is normally the order in which keys were inserted into the map (insertion-order).
That being said, LinkedHashMap
also supports access-order;
A special
constructor
is provided to create a linked hash map whose order of iteration is the order in which its entries were last accessed, from least-recently accessed to most-recently (access-order). This kind of map is well-suited to building LRU caches. Invoking theput
orget
method results in an access to the corresponding entry (assuming it exists after the invocation completes).
So, if you're using insertion-order, then the order will not change from get("b")
; if you're using access-order (which generally an LRU cache would ;-) then the order will change.
Any other questions? :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With