I was trying to implement a LRU cache using LinkedHashMap. In the documentation of LinkedHashMap (http://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashMap.html), it says:
Note that insertion order is not affected if a key is re-inserted into the map.
But when I do the following puts
public class LRUCache<K, V> extends LinkedHashMap<K, V> { private int size; public static void main(String[] args) { LRUCache<Integer, Integer> cache = LRUCache.newInstance(2); cache.put(1, 1); cache.put(2, 2); cache.put(1, 1); cache.put(3, 3); System.out.println(cache); } private LRUCache(int size) { super(size, 0.75f, true); this.size = size; } @Override protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { return size() > size; } public static <K, V> LRUCache<K, V> newInstance(int size) { return new LRUCache<K, V>(size); } }
The output is
{1=1, 3=3}
Which indicates that the re-inserted did affected the order. Does anybody know any explanation?
Abstract: The LinkedHashMap has an interesting feature, where we can order elements in "access order", rather than the default "insertion order". This allows us to build a light-weight LRU cache.
To implement an LRU cache we use two data structures: a hashmap and a doubly linked list. A doubly linked list helps in maintaining the eviction order and a hashmap helps with O(1) lookup of cached keys. Here goes the algorithm for LRU cache.
Implementing LRU Cache in Java Queue: Using a doubly-linked list, one can implement a queue where the max size of the queue will be equal to the cache size (the total number of frames that exist).
Answer: The main use of LinkedHashMap in Java is to use it for preserving the insertion order. It can also be used to preserve the access order using which the keys are accessed.
As pointed out by Jeffrey, you are using accessOrder. When you created the LinkedHashMap, the third parameter specify how the order is changed.
"true for access-order, false for insertion-order"
For more detailed implementation of LRU, you can look at this http://www.programcreek.com/2013/03/leetcode-lru-cache-java/
But you aren't using insertion order, you're using access order.
order of iteration is the order in which its entries were last accessed, from least-recently accessed to most-recently (access-order)
...
Invoking the put or get method results in an access to the corresponding entry
So this is the state of your cache as you modify it:
LRUCache<Integer, Integer> cache = LRUCache.newInstance(2); cache.put(1, 1); // { 1=1 } cache.put(2, 2); // { 1=1, 2=2 } cache.put(1, 1); // { 2=2, 1=1 } cache.put(3, 3); // { 1=1, 3=3 }
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