(1)双向链表数据结构
(2)LRC缓存淘汰策略
(3) 代码图解
(4) 实现代码
package com.cao.customerview.cache;
import java.util.HashMap;
import java.util.Map;
/**
* description: LRU least recently used 最近最少使用
*/
public class LRUCache {
public static void main(String[] args){
LRUCache cache = new LRUCache(3);
cache.put(1, 18);
cache.put(2, 28);
cache.put(3, 38);
System.out.println(cache);
cache.put(4, 48);
System.out.println(cache);
cache.get(2);
cache.put(5, 55);
System.out.println(cache);
cache.get(5);
cache.put(7, 15);
System.out.println(cache);
}
//双向链表数据结构
class CacheNode {
int key ; //缓存key
int val ; //缓存val
CacheNode pre ; //前节点指针
CacheNode next ; //后节点指针
}
//缓存容量最大值
private int maxSize ;
private CacheNode first ; //虚首节点
private CacheNode last ; //虚首节点
private Map<Integer,CacheNode> map ;
public LRUCache(int size){
this.maxSize = size ;
map = new HashMap<>(maxSize);
first = new CacheNode() ;
last = new CacheNode() ;
first.next = last ;
last.pre = first ;
}
//get
private int get(int key){
CacheNode node = map.get(key);
if (node==null){return -1;}
//查到数据了 放到首部 表示最新使用过的数据
moveToHead(node);
return node.val;
}
/**
* 移动到首部
* */
private void moveToHead(CacheNode node){
//把之前的位置删除
removeNode(node);
//添加节点
addNode(node);
}
/**
* 移除节点
* */
private void removeNode(CacheNode node){
node.pre.next = node.next ;
node.next.pre = node.pre ;
}
/**
* 添加节点
* */
private void addNode(CacheNode node){
// a - first
node.pre = first ;
//a-b
node.next = first.next ;
// b- a
first.next.pre = node ;
//first -a
first.next = node;
}
/**插入数据
* @param key
* @param val
* */
public void put(int key , int val){
CacheNode node = map.get(key) ;
if (node==null){
//初始化
node = new CacheNode() ;
node.key = key ;
node.val = val ;
if(map.size() == maxSize){
//删除双向链表的这个节点 并返回
CacheNode del = popTail();
//从map移除
map.remove(del.key);
}
map.put(key, node);
addNode(node);
}else {
//之前存在这个数据
node.val = val ;
moveToHead(node);
}
}
//删除双向链表的最后一个节点
private CacheNode popTail(){
//得到真实数据的最后一个节点
CacheNode node = last.pre ;
removeNode(node);
return node;
}
@Override
public String toString(){
return map.keySet().toString() ;
}
}