如何实现 LRU 缓存淘汰算法 如何实现 LRU 缓存淘汰算

如何实现 LRU 缓存淘汰算法

这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

笔者最近在学习《数据结构与算法之美》,正好借着这个机会边练习边记录一下自己学习的知识点。不啰嗦,直接开始。

一、什么是缓存

缓存 一种提高数据读取性能的技术,有着广泛的应用,例如常见的 CPU 缓存、数据库缓存、浏览器缓存等等。

二、常见的缓存淘汰策略

缓存的大小是有限的。当缓存满了,哪些缓存数据应该被清除,哪些缓存数据应该被保留?这就应该由缓存淘汰策略来决定缓存数据的去留。常见的缓存淘汰策略有三种:

  • 先进先出策略 FIFO:先进入缓存中的数据,先被淘汰。
  • 最少使用策略 LFU:最近使用频率最少的缓存数据,先被淘汰。
  • 最近最少使用策略 LRU:最近一段时间最少被访问的数据,先被淘汰。

这里帮大家举个例子去记忆这三种淘汰策略,例如去年双十一买了一堆没用却用没有退货的东西,今年双十一又剁手买了一堆没有用的东西,房间堆满了,哪些该被清理掉?是不是我们清理的东西想法和这三种淘汰策略不谋而合了。接下来看我们今天的主角 LRU 最近最少使用策略具体实现思路吧。

三、LRU 淘汰策略实现思路

  • 缓存没有满时,新数据就放到缓存的前面。
  • 缓存已经满了,这是需要分两种情况去讨论:
    • 一是新的数据之前已经存在缓存中,此时我们需要将之前存在缓存中的数据清出缓存,再将新数据放到缓存的前面。
    • 二是新数据不在缓存中,此时我们需要先清除缓存中最后一个数据,再将新数据放到缓存的前面。

从这个思路我们可以看到,LRU 缓存淘汰策略的一个特点,需要频繁的进行数据插入删除操作。那么那种数据结构擅长进行删除和插入操作的呢?答案呼之欲出:链表。ok,接下来我们就使用链表结合实现思路转换成具体的代码。

四、LRU 淘汰策略代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
java复制代码import java.util.LinkedList;

/**
* @author xuls
* @date 2021/11/14 16:23
* LRU 缓存淘汰算法
*/
public class LRU <T>{
private LinkedList<T> list;
private int capacity; //缓存容量

public LRU() {
this(10);
}

public LRU(int capacity) {
this.capacity = capacity;
list = new LinkedList<>();
}

public void add(T data){
if (list.size() < capacity){
//缓存未满,直接添加到链表头部,表明该数据最近在使用
list.addFirst(data);
}else {
//链表之中是否包含 data
if (list.contains(data)){
//链表包含 data ,先将包含的数据移除
list.remove(data);
}else {
//链表不包含 data ,移除最后一个,因为最后一个是最近最少使用的
list.removeLast();
}
//将新数据添加到前面
list.addFirst(data);
}
}

@Override
public String toString() {
return "LRU{" +
"list=" + list +
'}';
}

public static void main(String[] args) {
LRU<String> stringLRU = new LRU<>();
for (int i = 0; i < 10; i++) {
stringLRU.add("s"+i);
}
System.out.println(stringLRU);
stringLRU.add("s1");
System.out.println(stringLRU);
stringLRU.add("s10");
System.out.println(stringLRU);
}
}

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%