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
Mapinterface, with predictable iteration order. This implementation differs fromHashMapin 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
constructoris 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 theputorgetmethod 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