设计一个LRU Cache

原来遇到的一个面试题,今天意外想起,记录一下。


问题:设计实现一个LRU Cache,需要支持三种操作:插入(insert)、替换(replace)、查找(lookup)

思路:用HashMap做为基础容器,容器内Value组成双向链表,由双向链表支持LRU的替换策略。

链表需要维持数据项从最近访问到最旧访问的顺序。

  • 插入:当Cache未满时,新的数据项只需插到双链表头部即可。时间复杂度为O(1)O(1).

  • 替换:当Cache已满时,将新的数据项插到双链表头部,并删除双链表的尾结点即可。时间复杂度为O(1)O(1).

  • 查找:每次数据项被查询到时,都将此数据项移动到链表头部。

设计一个LRU Cache_第1张图片

实现:

Java实现非常简单,LinkedHashMap自身已经实现了顺序存储,默认情况下是按照元素的添加顺序存储,也可以启用按照访问顺序存储,即最近读取的数据放在最前面,最早读取的数据放在最后面,然后它还有一个判断是否删除最老数据的方法,默认是返回false,即不删除数据,我们使用LinkedHashMap实现LRU缓存的方法就是对LinkedHashMap实现简单的扩展。



public static class LRULinkedHashMap extends LinkedHashMap {  
  
        /** serialVersionUID */  
        private static final long serialVersionUID = -5933045562735378538L;  
  
        /** 最大数据存储容量 */  
        private static final int  LRU_MAX_CAPACITY     = 1024;  
  
        /** 存储数据容量  */  
        private int               capacity;  
  
        /** 
         * 默认构造方法 
         */  
        public LRULinkedHashMap() {  
            super();  
        }  
  
        /** 
         * 带参数构造方法 
         * @param initialCapacity   容量 
         * @param loadFactor        装载因子 
         * @param isLRU             是否使用lru算法,true:使用(按方案顺序排序);false:不使用(按存储顺序排序) 
         */  
        public LRULinkedHashMap(int initialCapacity, float loadFactor, boolean isLRU) {  
            super(initialCapacity, loadFactor, true);  
            capacity = LRU_MAX_CAPACITY;  
        }  
  
        /** 
         * 带参数构造方法 
         * @param initialCapacity   容量 
         * @param loadFactor        装载因子 
         * @param isLRU             是否使用lru算法,true:使用(按方案顺序排序);false:不使用(按存储顺序排序) 
         * @param lruCapacity       lru存储数据容量        
         */  
        public LRULinkedHashMap(int initialCapacity, float loadFactor, boolean isLRU, int lruCapacity) {  
            super(initialCapacity, loadFactor, true);  
            this.capacity = lruCapacity;  
        }  
  
        /**  
         * @see java.util.LinkedHashMap#removeEldestEntry(java.util.Map.Entry) 
         */  
        @Override  
        protected boolean removeEldestEntry(Entry eldest) {  
            System.out.println(eldest.getKey() + "=" + eldest.getValue());  
              
            if(size() > capacity) {  
                return true;  
            }  
            return false;  
        }  
    } 

你可能感兴趣的:(算法)