Java简易实现LRU算法
前言:
我们平常会使用缓存来提升我们的查询速度,由于缓存容量有限,就需要删除部分数据来挪出空间.但是我们缓存的数据不能随机删除,这样我们就需要特定的算法来支撑来删除数据.常见的算法有:LRU,FIFO等.我们先来介绍LRU算法!
LRU简介:
LRU是Least Recently Used的缩写.这种算法被认为最近使用的数据是热门数据,下一次很大概率将会被再次使用,而最近很少使用的数据,将很大概率会不再被使用到,当缓存容量满了的时候,将优先淘汰使用频率少的数据.
LRU簡易實現圖:
实现:
这个LRU算法是一个常用的算法,那我们该用什么数据结构去实现它呢?是我们常用底层为数据结构的ArrayList,还是底层为双向链表的LinkedList呢?还是其他的呢?
常用的数据结构优缺点比较(针对LRU算法):
- ArrayList:当我们需要给这个集合增加数据的时候,因为底层为数组,内存空间是连续的,此节点后面的节点都需要移动,会非常的消耗性能(会有大量的内存拷贝操作.)
- LInkedList:底层为双向链表,我们添加一个头结点,或者删除一个尾结点,时间复杂度都是O(1).这个只需要改变链表中的指针就可以了(不懂的可以去科普一下链表哦).
总结: 我们可以用 HashMap+双向链表来实现LRU算法.为什么不用队列,单链表,LinkedHashMap呢?以下具体说明:
队列:插入和删除的时候时间复杂度做不到O(1).
单链表:在我们链表中找到一个元素时,可以直接通过父节点指向子节点,把这个元素可以直接放到头部上,免去了遍历查找,时间复杂度是O(1),这单链表是做不到的.
LInkedHashMap:从全局维度看不够灵活,不方便做增强装饰.
//节点类
public class DLinkedNode {
String key;
Integer value;
//前节点
DLinkedNode pre;
//尾结点
DLinkedNode post;
}
public class LRUCache {
HashMap<String, DLinkedNode> cache = new HashMap<>();
//初始值容量
private int capacity;
//私有的头和尾
private