分析学习API文档实现LRU缓存置换算法的思路流程

需求:设计一个缓存类,利用LRU算法机制实现插入和删除数据。

分析

  关于LRU缓存在乐扣中的解答是通过Java API中LinkedHashMap这个类来实现,实现步骤如下:
  1.在定义的LRU缓存类中声明一个缓存容量和一个LinkedHashMap类型的变量
  2.在这个类的构造方法中给这个类的容量大小赋值,构造一个空的 LinkedHashMap实例,具有指定的初始容量(initialCapacity),负载因子(loadFactor)和排序模式(accessOrder)。

  • initialCapacity:容量大小,一般默认为16
  • loadFactor:就是容量扩容的一个阈值。更直白一些,如果我们把负载因子设置为0.5f,初始的容量是12,那么当容量到达6时就会开始扩容。文档给定的默认值就是0.75f,这是结合空间和时间利用率得出的结论。
  • accessOrder:排序模式有两种:true:代表访问模式;false:代表插入模式,这里用true,就表示双链表在头插法插入数据,当再次被访问时又会放到最前面的结点上,这是符合LRU缓存机制的。具体这两者的不同,请参考:关于LRU缓存机制中
    accessOrder不同排序模式的对比(含代码)

    3.书写一个匿名内部类,在里面重写删除老的键值对方法removeEldestEntry。参考Java API文档的LinkedHashMap类。
    4.继续在这个类里书写put方法,参考HasMap的put方法。
    5.书写getOrDefault方法,获取指定key值的value,若不存在则返回-1
    下面是上述流程的代码实现:
public class LRUdemo2 {
	int capacity;
	LinkedHashMap<Integer, Integer> linkedhashmap;

	public LRUdemo2(int capacity) {
		this.capacity = capacity;
		linkedhashmap = new LinkedHashMap<Integer, Integer>(capacity, 0.75f, true) {
			@Override
			protected boolean removeEldestEntry(Map.Entry eldest) {
				return linkedhashmap.size() > capacity;
			}
		};
	}

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

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

测试代码:

public static void main(String[] args) {
		LRUdemo2 lru = new LRUdemo2(2);
		lru.put(1, 1);// (head<=>1<=>tail)
		lru.put(2, 2);// (head<=>2<=>1<=>tail)
		System.out.println(lru.get(1));// 返回key=1,并把key=1的结点添加到head结点后面(head<=>1<=>2<=>tail)
		lru.put(3, 3);// (head<=>3<=>1<=>tail)
		System.out.println(lru.get(2));// key=2,不存在,不进行操作,等待添加进去
		lru.put(4, 4);// (head<=>4<=>3<=>tail)
		System.out.println(lru.get(1));// key=1,不存在,不进行操作,等待添加进去
		System.out.println(lru.get(3));// 添加后(head<=>3<=>4<=>tail)
		System.out.println(lru.get(4));// 添加后(head<=>4<=>3<=>tail)
	}

另外最后,还有一种思路更好理解的方法,也更加便于实践,那就是手动写双链表+hashmap的结构,这里希望一并清楚的将思路介绍给大家,权当练习思路。
1)定义一个链表类,里面有key、value、表示前一个和后一个的链表结点。
2)在URLDemo1中声明一个HasMap和存储的最大限度,键为包裹类Integer,值为链表类型,构造并实例化两个结点表示这个双向链表的头和尾,并在构造方法中初始化头尾关系
3)书写put方法,先判断要放入的数据是不是已经在这个hashmap中存放了,如果没存放 { 就继续判断,这个hashmap的容量是不是等于我们规定的最大限度,如果超过了就先删除双向双向链表的最后一个结点,接着继续将要插入数据放入双向链表的头部,} 如果存放了就需要修改后再次放到双向链表的头部。
4)书写get方法,如果map中存在这个数据,直接将其的值返回出来,并且还需要将这个数据放到双向链表的头部,如果map中不存在则返回-1。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值