java实现LRU缓存

java实现LRU缓存

LRU缓存: least recent used:最久不使用的淘汰;

特点:

  • 加入或者更新将其移到最前面;
  • 缓存不够了需要删除最久未使用的。

实现结构: 双链表

定义双链表节点:

/**
 * 双链表的节点
 */
public class Node {
    Object key;
    Object value;
    Node pre;
    Node next;

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

    @Override
    public String toString() {
        return "{"+key+":"+value+"}";
    }
}

Lru缓存实现

/**
 * Lru缓存
 * 不用就淘汰,用过就排在最前面
 * 存不下的时候才淘汰
 * 双链表:null--last--node1--node2--...node--first--null
 * 初始状态 first=last=null
 */
public class LruCache<K,V> {
    private int size;
    private int currentSize;
    private HashMap<K,Node> caches;
    private Node first;//头节点
    private Node last;//尾节点

    //构造类,指定容量
    public LruCache(int size){
        currentSize=0;
        this.size=size;
        caches=new HashMap<K,Node>(size);
    }
    
    public String printCache(){
        Node node=first;
        String cacheStr="";
        while (node!=null){
            cacheStr+=node.toString()+"->";
            node=node.next;
        }
        return cacheStr;
    }
}

加入缓存

 //加入缓存
    public void put(K key,V value){
        //如果是新元素,需要更新值
        Node node=caches.get(key);
        if(node==null){
            //是否超过容量
            if(caches.size()>=size){
                remove((K) last.key);//移除
            }
            node=new Node(key,value);
            caches.put(key,node);
        }else{
            node.value=value;
        }
        //将最新元素移动到头节点
        moveToHead(node);
    }

取缓存

//取缓存
    public Object get(K key){
        Node node=caches.get(key);
        if(node==null){
            return null;
        }
        moveToHead(node);
        return node.value;
    }

删除元素

/**
     * 删除元素
     * @param key
     */
    private Object remove(K key){
        Node node=caches.get(key);
        if(node!=null){
            if(node.pre!=null){
                node.pre.next=node.next;
            }
            if(node.next!=null){
                node.next.pre=node.pre;
            }
            if(node==first){
                first=node.next;
            }
            if(node==last){
                last=node.pre;
            }
        }
        return caches.remove(key);
    }

私有方法:将节点移动为头节点

/**
     * 将某个节点移动到头节点,在添加节点/更新节点的时候执行:
     * node.pre.next=node.next;
     * node.next.pre=node.pre;//原链表重link
     * node.next=first;first.pre=node;first=node;first.pre=null;
     * @param node
     */
    private void moveToHead(Node node){
        if(first==node){
            return;
        }
        if(node.next!=null){
            node.next.pre=node.pre;
        }
        if(node.pre!=null){
            node.pre.next=node.next;
        }
        if(node==last){
            last=last.pre;
        }
        //空链表
        if(first==null||last==null){
            first=last=node;
            return;
        }
        //更换头节点
        node.next=first;
        first.pre=node;
        first=node;
        first.pre=null;//是否有必要?
    }

测试


    public static void main(String[] args) {
        LruCache<Integer,String> lru=new LruCache<Integer,String>(5);
        lru.put(1,"a");
        lru.put(2,"b");
        lru.put(3,"c");
        lru.put(4,"d");
        lru.put(5,"e");
        System.out.println("当前链表为"+lru.printCache());
        lru.put(6,"F");//一般首先是溢出缓存
        System.out.println("当前链表为"+lru.printCache());
        System.out.println("获取元素"+lru.get(4)+",现在链表为:"+lru.printCache());
        System.out.println("移除元素"+lru.remove(3)+",现在链表为:"+lru.printCache());
    }

测试结果

当前链表为{5:e}->{4:d}->{3:c}->{2:b}->{1:a}->
当前链表为{6:F}->{5:e}->{4:d}->{3:c}->{2:b}->
获取元素d,现在链表为:{4:d}->{6:F}->{5:e}->{3:c}->{2:b}->
移除元素{3:c},现在链表为:{4:d}->{6:F}->{5:e}->{2:b}->
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值