LRU 缓存机制

题目:

  LRU 缓存机制

 思路:

   1    运用 LinkedHashMap  已经实现好的LRU 

    继承 LinkedHashMap  重写 removeEldestEntry 方法  当size() > capatity 返回true 

 

  2   使用HashMap 和 双向链表

     读缓存时从HashMap 中查找key,更新缓存时同时更新HashMap和双向链表,双向链表始终按照访问顺序排列


 (一)代码 使用LinkedHashMap

public class LRUCache extends LinkedHashMap<Integer,Integer>{

    //容量
    private int capacity;

    public LRUCache(int capacity) {
        super(capacity,0.75F,true);
        this.capacity = capacity;
    }

    public int get(int key){
        return super.getOrDefault(key,-1);
    }

    public void put(int key,int value){
        super.put(key,value);
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry eldest){
        return size() > capacity;
    }
}

 


 

(二)使用HashMap 和 双向链表

public class LRUCache {

    //缓存容量
    private final int capacity;

    //用于加速缓存项随机访问性能的hashmap
    private HashMap<Integer, Entry> map;

    //双向链表头结点
    private Entry head;

    //双向链表尾节点
    private Entry tail;

    public LRUCache(int capacity) {
        this.capacity = capacity;
        head = new Entry(0,0);
        tail = new Entry(0,0);
        head.next = tail;
        tail.prev = head;
        map = new HashMap<Integer,Entry>();
    }

    public int get(int key){
        //如果是已经存在的,更新值到末端,移除是从头进行移除(相当于放到了最新的位置)
        if(map.containsKey(key)){
            Entry entry = map.get(key);
            popToTail(entry);
            return entry.value;
        }
        return -1;
    }

    public void put(int key,int value){

        //如果key存在,就更新value
        if(map.containsKey(key)){
            Entry entry = map.get(key);
            entry.value = value;
        }else{
            Entry entry = new Entry(key,value);
            if(map.size() > capacity){
                Entry first = removeFirst();
                map.remove(first.key);
            }
            addToTail(entry);
            map.put(key,entry);
        }

    }

    class Entry{
        int key,
        int value,
        Entry prev,
        Entry next,

        Entry(int key,int value){
            this.key = key;
            this.value = value;
        }
    }

    //移除链表首端节点
    private Entry removeFirst(){

        Entry first = head.next;
        Entry second = first.next;
        head.next = second;
        second.prev = head;

        return first;
    }

    //添加 entry 节点到链表末端
    private void addToTail(Entry entry){

        Entry last = tail.prev;
        last.next = entry;
        tail.prev = entry;
        entry.prev = last;
        entry.next = tail;
    }

    //将entry 节点移动到链表末端
    private void popToTail(Entry entry){

        //1 删除 entry 当前位置信息
        Entry prev = entry.prev;  //entry 的前指针
        Entry next = entry.next;  //entry 的后指针
        //让前指针 指向 后指针 , 后指针指向前指针,从而达到删除的目的
        prev.next = next;
        next.prev = prev;

        //2 添加到末尾的位置
        Entry last = tail.prev;
        last.next = entry;  //插入点的前节点的 next 指针指向entry
        tail.prev = entry;  //插入点的后节点的 prev 指针指向entry
        entry.prev = last;  //更新entry 的前指针
        entry.next = tail;  //更新entry 的后指针

    }

}

 


 

 

 

        今晚吃凉皮

 

       

 

LRU 缓存机制

上一篇:HTTP -> Asp.net (第一篇)


下一篇:dubbo从入门到精通 常用的dubbo配置,重试次数、多版本(灰度发布)、本地存根(十)