基于 LinkedHashMap 实现LRU缓存调度算法原理

基于 LinkedHashMap 如何实现LRU缓存调度算法原理

LRU这个算法就是把最近一次使用时间离现在时间最远的数据删除掉

Redis 内存淘汰机制 :
allkeys-lru(least recently used):当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)

List:每次访问一个元素后把这个元素放在 List一端,这样一来最远使用的元素自然就被放到List的另一端。缓存满了的时候就把那最远使用的元素remove掉
但是List太慢,因为List底层是数组 , 要删掉的数据总是位于List底层数组的第一个位置,删掉之后,后面的数据要向前补位, 所以复杂度是O(n)

Map : 链表结构的 LinkedHashMapLinkedHashMap 默认的元素顺序是 put 的顺序,但是如果使用带参数的构造函数,那么 LinkedHashMap 会根据访问顺序来调整内部顺序。 LinkedHashMap的get()方法除了返回元素之外还可以把被访问的元素放到链表的底端,这样一来每次顶端的元素就是remove的元素。

仿照Redis 内存淘汰机制的原理,可以自己利用LinkedHashMap写一个LRU算法。

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author : cpucode
 * @date : 2021/5/23
 * @time : 16:26
 * @github : https://github.com/CPU-Code
 * @csdn : https://blog.csdn.net/qq_44226094
 */
public class UrlTest {
    public static void main(String[] args) {
        LinkedHashMap<String, String> map = createUrlMap();

        System.out.println("/*******************使用bb************************/");
        map.get("bb");
        System.out.println(map);

        System.out.println("/*******************使用aa************************/");
        map.get("aa");
        System.out.println(map);

        System.out.println();

        System.out.println("/*******************加入ee************************/");
        map.put("ee","55");
        System.out.println(map);

        System.out.println("/*******************加入ff************************/");
        map.put("ff","66");
        System.out.println(map);
    }

    static final int MAX_NUM = 5;

    public static LinkedHashMap<String, String> createUrlMap() {
        LinkedHashMap<String, String> map = null;

        /**
         * @param MAX_NUM  初始容量
         * @param 0.75F    加载因子,一般是 0.75f
         * @param true     false 基于插入顺序  true  基于访问顺序(get一个元素后,这个元素被加到最后,使用了LRU  最近最少被使用的调度算法)
         */
        map = new LinkedHashMap<String, String>(MAX_NUM,0.75F ,true){

            /**
             * 实现LRU的关键方法,如果map里面的元素个数大于了缓存最大容量,则删除链表的顶端元素
             *
             * @param var
             * @return
             */
            @Override
            protected boolean removeEldestEntry(Map.Entry<String, String> var){
                return this.size() > MAX_NUM;
            }

        };

        map.put("aa", "11");
        map.put("bb", "22");
        map.put("cc", "33");
        map.put("dd", "44");

        System.out.println("/******************正常顺序************************/");
        System.out.println(map);
        System.out.println();

        return map;
    }
}

结果 :

/******************正常顺序************************/
{aa=11, bb=22, cc=33, dd=44}

/*******************使用bb************************/
{aa=11, cc=33, dd=44, bb=22}
/*******************使用aa************************/
{cc=33, dd=44, bb=22, aa=11}

/*******************加入ee************************/
{cc=33, dd=44, bb=22, aa=11, ee=55}
/*******************加入ff************************/
{dd=44, bb=22, aa=11, ee=55, ff=66}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值