【缓存算法】LRU 最近最少使用

LRU是Least Recently Used,最近最少使用。
LRU缓存就是使用这种原理实现,简单的说就是缓存一定量的数据,当超过设定的阈值时就把一些过期的数据删除掉。

LRU思想

  • 固定缓存大小,需要给缓存分配一个固定的大小。
  • 每次读取缓存都会改变缓存的使用时间,将缓存的存在时间重新刷新。
  • 需要在缓存满了后,将最近最久未使用的缓存删除,再添加最新的缓存。

【缓存算法】LRU 最近最少使用_第1张图片

Java实现

  • HashMap + 双向链表
/**
 * @author huangliuyu
 * @description LRU 最近最久未使用
 * @date 2019-05-10
 */
public class LRUCache {
    private Node head;
    private Node end;
    //缓存存储上限
    private int limit;

    private HashMap<String, Node> hashMap;

    public LRUCache(int limit){
        this.limit=limit;
        hashMap=new HashMap<String, Node>();
    }


    public String get(String key){
        Node node=hashMap.get(key);
        if(null==node){
            return null;
        }
        this.refreshNode(node);
        return node.value;
    }

    public void put(String key, String value){
        Node node = hashMap.get(key);
        //如果key不存在,插入key-value
        if(null==node){
            //临界值,清理最少使用节点
            if(hashMap.size()>=limit){
                String oldKey=this.removeNode(head);
                hashMap.remove(oldKey);
            }
            node=new Node(key,value);
            this.addNode(node);
            hashMap.put(key,node);

        //如果key存在,则刷新kye-value
        }else {
            node.value=value;
            this.refreshNode(node);
        }
    }

    public void remove(String key){
        Node node=hashMap.get(key);
        this.removeNode(node);
        hashMap.remove(key);

    }

    /**
     * 刷新被访问的节点
     * @param node
     */
    private void refreshNode(Node node){
        //如果访问的尾节点,无需移动节点
        if(node ==end){
            return;
        }
        //移除节点
        this.removeNode(node);
        //重新插入节点
        this.addNode(node);
    }


    /**
     * 删除节点
     * @param node
     * @return
     */
    private String removeNode(Node node){
        if(node==end){
            //移除尾节点
            end=end.pre;
        }else if(node==head.next){
            //移除头节点
            head=head.next;
        }else {
            node.pre.next=node.next;
            node.next.pre=node.pre;
        }
        return node.key;
    }



    /**
     * 尾部插入节点
     * @param node
     */
    private void addNode(Node node){
        if(null!=end){
            end.next=node;
            node.pre=end;
            node.next=null;
        }
        end=node;
        if(null==head){
            head=node;
        }
    }



    class Node{
        public Node pre;
        public Node next;
        public String key;
        public String value;

        Node(String key, String value){
            this.key=key;
            this.value=value;
        }
    }


}

你可能感兴趣的:(数据结构与算法,Java,LRU,最近最少使用)