LRU Cache 暨LinkedHashMap源码阅读

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set.

get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
set(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

题目要求:定义一种数据结构,实现LRU算法(最近最少使用)。


一开始觉得,可以使用LinkedHashMap实现,但没提供按照顺序删除指定范围KEY-VALUE映射的API;后拉,看到了

这篇blog: 如何用LinkedHashMap实现LRU缓存算法,才知道如何下手……自己代码看的还是太浅了。


public class LRUCache {
    static class LRULinkedHashMap<K,V> extends java.util.LinkedHashMap<K,V>{
        private int capacity;  
        private static final long serialVersionUID = 1L;  
        public LRULinkedHashMap(int capacity){  
            super(capacity,0.75f,true);  
            this.capacity=capacity;  
        } 
        @Override  
        public boolean removeEldestEntry(Map.Entry<K, V> eldest){
            return size()>capacity;  
        }
    }
    
    private LRULinkedHashMap<Integer,Integer> map ;
    
    public LRUCache(int capacity) {
        map = new LRULinkedHashMap<>(capacity);
    }
    
    public int get(int key) {
        if(!map.containsKey(key)){
            return -1;
        }
        Integer val = map.get(key);
        return val;
    }
    
    public void set(int key, int value) {
        map.put(key,value);
    }
}


----------------------------------------------------------------------------------------


先看一下LinkedHashMap的构造器,


public class LinkedHashMap<K,V>
    extends HashMap<K,V>
    implements Map<K,V>
{

    private static final long serialVersionUID = 3801124242820219131L;

    private transient Entry<K,V> header;

    private final boolean <strong>accessOrder</strong>;

    public LinkedHashMap(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor);
        accessOrder = false;
    }

    public LinkedHashMap(int initialCapacity) {
        super(initialCapacity);
        accessOrder = false;
    }

    public LinkedHashMap() {
        super();
        accessOrder = false;
    }

    public LinkedHashMap(Map<? extends K, ? extends V> m) {
        super(m);
        accessOrder = false;
    }


    public LinkedHashMap(int initialCapacity,
                         float loadFactor,
                         boolean accessOrder) {
        super(initialCapacity, loadFactor);
        this.accessOrder = accessOrder;
    }
重点在于属性accessOrder表示:

true时,按照KEY-VALUE的访问顺序;

false时,按照KEY-VALUE的插入顺序;


accessOrder可用于保证实现LRU。


/**
     * Returns <tt>true</tt> if this map should remove its eldest entry.
     * This method is invoked by <tt>put</tt> and <tt>putAll</tt> after
     * inserting a new entry into the map.  It provides the implementor
     * with the opportunity to remove the eldest entry each time a new one
     * is added.  This is useful if the map represents a cache: it allows
     * the map to reduce memory consumption by deleting stale entries.
     *
     * <p>Sample use: this override will allow the map to grow up to 100
     * entries and then delete the eldest entry each time a new entry is
     * added, maintaining a steady state of 100 entries.
     * <pre>
     *     private static final int MAX_ENTRIES = 100;
     *
     *     protected boolean removeEldestEntry(Map.Entry eldest) {
     *        return size() > MAX_ENTRIES;
     *     }
     * </pre>
     *
     * <p>This method typically does not modify the map in any way,
     * instead allowing the map to modify itself as directed by its
     * return value.  It <i>is</i> permitted for this method to modify
     * the map directly, but if it does so, it <i>must</i> return
     * <tt>false</tt> (indicating that the map should not attempt any
     * further modification).  The effects of returning <tt>true</tt>
     * after modifying the map from within this method are unspecified.
     *
     * <p>This implementation merely returns <tt>false</tt> (so that this
     * map acts like a normal map - the eldest element is never removed).
     *
     * @param    eldest The least recently inserted entry in the map, or if
     *           this is an access-ordered map, the least recently accessed
     *           entry.  This is the entry that will be removed it this
     *           method returns <tt>true</tt>.  If the map was empty prior
     *           to the <tt>put</tt> or <tt>putAll</tt> invocation resulting
     *           in this invocation, this will be the entry that was just
     *           inserted; in other words, if the map contains a single
     *           entry, the eldest entry is also the newest.
     * @return   <tt>true</tt> if the eldest entry should be removed
     *           from the map; <tt>false</tt> if it should be retained.
     */
    protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
        return false;
    }


则保证删除最老(最近未被使用)的元素,只有当返回false时,才生效。


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。