Java 实现LRU 算法(缓存清除经典算法)

目录

LinkedHashMap 源码解析

Java 实现LRU算法


LRU:Last Recent Used 最近最少使用 算法

是一种常见的缓存清除算法。被广泛应用在各种缓存中间件比如Redis 中。

比较常见的实现是LinkedHashMap

LinkedHashMap 源码解析

可以理解,它的主要特点是:

1.这是一个链表。

2.每次插入一个数据都放在最头部,之前的数据往里推,如果长度超过了最大值,就删除最尾部的数据。

3.每访问一个数据,就移到最头部。

LinkedHashMap 中每一个Entry 都是继承自HashMap 的Node

    static class Entry<K,V> extends HashMap.Node<K,V> {
        Entry<K,V> before, after;
        Entry(int hash, K key, V value, Node<K,V> next) {
            super(hash, key, value, next);
        }
    }

Entry 都有对前一个对象和后一个对象的引用,保存当前的key 和 value。

    /**
     * The head (eldest) of the doubly linked list.
     */
    transient LinkedHashMap.Entry<K,V> head;

    /**
     * The tail (youngest) of the doubly linked list.
     */
    transient LinkedHashMap.Entry<K,V> tail;

定义了头部和尾部

Java 实现LRU算法


/**
 * @ClassName LRUCache
 * @Description TODO
 * @Author xl
 * @Date 2019/7/19 20:15
 * @Version 1.0
 */
public class LRUCache<K,V> {

    private int currentCacheSize;
    private int cacheCapacity;
    private HashMap<K,CacheNode> caches;
    private CacheNode header;
    private CacheNode tail;

    public LRUCache(int size){
        currentCacheSize = 0;
        this.cacheCapacity = size;
        caches = new HashMap<>(size);
    }

    public void put(K k,V v){
        CacheNode node = caches.get(k);
        if(node == null){
            if(caches.size() >= cacheCapacity){
                caches.remove(tail.key);
                removeLast();
            }
            node = new CacheNode();
            node.key = k;
        }
        node.value = v;
        moveToFirst(node);
        caches.put(k,node);
    }

    public Object get(K k){
        CacheNode node = caches.get(k);
        if(node == null){
            return null;
        }
        moveToFirst(node);
        return node.value;
    }

    public Object remove(K k) {
        CacheNode node = caches.get(k);
        if (node != null) {
            // 有可能它不是第一个
            if (node.pre != null) {
                node.pre.next = node.next;
            }
            // 有可能它不是最后一个
            if (node.next != null){
                node.next.pre = node.pre;
            }

            if(node == header){
                header = node.next;
            }
            if(node == tail){
                tail = node.pre;
            }
        }
        return caches.remove(k);
    }

    public void removeLast(){
        if(tail != null){
            tail = tail.pre;
            if(tail == null){
                header = null;
            }else{
                tail.next = null;
            }
        }
    }

    public void clear(){
        tail = null;
        header = null;
        caches.clear();
    }

    public void moveToFirst(CacheNode node){
        if(header == node){
            return ;
        }

        if(node.next != null){
            node.next.pre = node.pre;
        }

        if(node.pre!=null){
            node.pre.next = node.next;
        }

        if(node == tail){
            tail = node.pre;
        }

        if(tail == null || header == null){
            tail = header = node;
            return ;
        }

        node.next = header;
        header.pre = node;
        header = node;
        header.pre = null;
    }

    class CacheNode{
        CacheNode pre;
        CacheNode next;
        Object key;
        Object value;

        public CacheNode(){

        }
    }

    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();
        CacheNode node = header;
        while (node != null) {
            sb.append(String.format("%s%s",node.key,node.value));
            node = node.next;
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        LRUCache<Integer,String> lru = new LRUCache<>(3);
        lru.put(1,"a");
        System.out.println("lru : "+lru.toString());

        lru.put(2,"b");
        System.out.println("lru : "+lru.toString());

        lru.put(3,"c");
        System.out.println("lru : "+lru.toString());

        lru.put(4,"d");
        System.out.println("lru : "+lru.toString());

        lru.put(1,"aa");
        System.out.println("lru : "+lru.toString());

        lru.put(2,"bb");
        System.out.println("lru : "+lru.toString());

        lru.get(4);
        System.out.println("lru : "+lru.toString());

        lru.remove(2);
        System.out.println("lru : "+lru.toString());
    }


}

 

参考:

缓存淘汰算法--LRU算法(java代码实现)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值