package com.LRU;
import java.util.StringJoiner;
import java.util.concurrent.ConcurrentHashMap;
public class LUR20210428<K,V> {
/**
* 初始化 LRU 缓存类
*
* @param cacheSize 缓存链的大小
*/
LUR20210428(int cacheSize){
//缓存链的大小
this.cacheSize=cacheSize;
//初始化 map 大小
data=new ConcurrentHashMap<>(cacheSize);
//初始化 链的头
first=new Node();
first.last=null;
//初始化 链的尾
penultimate=new Node();
penultimate.nest=null;
//初始化 链的头尾相连
first.nest=penultimate;
penultimate.last=first;
}
// 缓存数据的长度
private int cacheSize;
// 目前数据大小
private int count=0;
// 第一个节点
private Node first;
// 最后一个节点
private Node penultimate;
//存储数据的结构
ConcurrentHashMap<K,Node> data;
//存储数据的类
class Node{
Node last;
Node nest;
K key;
V value;
}
//获取数据大小
int getSize(){
return count;
}
/**
* 通过key获取数据
* @param key
* @return
*/
public synchronized V get(K key){
Node node = data.get(key);
if(node==null){
return null;
}
//如果数据不为null 删除链中的节点
removeOne(node);
// 然后把这个节点 添加到头部
insertFirst(node);
return data.get(key).value;
}
/**
* 添加缓存数据
* @param key
* @param value
* @return
*/
public synchronized Boolean put(K key,V value){
Node node = data.get(key);
if(node!=null){
//已有该数据 则删除链中的数据 并把它添加到头部
node.value=value;
removeOne(node);
insertFirst(node);
}else {
//没有该数据 则新建node 并把它添加到头部
node = new Node();
node.key=key;
node.value=value;
insertFirst(node);
}
//最后更新到map
data.put(key,node);
return true;
}
/**
* 通过key删除节点
* @param key
* @return
*/
public synchronized Boolean remove(K key){
Node node = data.get(key);
if(node!=null){
removeOne(node);
return true;
}
return false;
}
/**
* 私有方法 把node添加到头部
* @param node
* @return
*/
private Node insertFirst(Node node){
//如果 数据大小 接近了 缓存设置大小 则删除最末尾的数据
if (count>=cacheSize){
removeLastOne();
}
// 把数据插到 first 后面的节点
Node oldFirst = first.nest;
oldFirst.last=node;
node.nest=oldFirst;
node.last=first;
first.nest=node;
count++;
return node;
}
/**
* 私有的 删除节点 并删除map中的数据
* @param node
*/
private void removeOne(Node node){
data.remove(node.key);
Node last= node.last;
Node nest= node.nest;
last.nest=nest;
nest.last=last;
count--;
}
/**
* 私有化 删除末尾淘汰的节点
*/
private void removeLastOne(){
//先删除data中这个节点的数据
data.remove(penultimate.last.key);
// 然后 删除掉链中的末尾的数据
Node needRemoveNode = penultimate.last;
Node newPenultimate = needRemoveNode.last;
newPenultimate.nest=penultimate;
penultimate.last=newPenultimate;
count--;
}
/**
* 可视化输出 链数量 和 链结构 方便查看运行过程
*/
public void printLink(){
StringJoiner stringJoiner=new StringJoiner(">");
Node firstNode=first.nest;
while (firstNode.nest!=null){
stringJoiner.add(firstNode.key+"");
firstNode=firstNode.nest;
}
System.out.println( "count :"+count+"|" + stringJoiner.toString());
}
}
测试
package com.LRU;
import java.util.concurrent.locks.ReentrantLock;
public class test {
public synchronized static void main(String[] args) {
LUR20210428<Integer,Integer> lruCache= new LUR20210428<Integer, Integer>(4);
lruCache.put(1,10);
lruCache.put(2,20);
lruCache.put(3,30);
lruCache.printLink();
lruCache.put(4,40);
lruCache.printLink();
lruCache.put(4,40);
lruCache.printLink();
lruCache.put(4,40);
lruCache.printLink();
lruCache.put(5,50);
lruCache.printLink();
lruCache.remove(4);
lruCache.remove(5);
lruCache.printLink();
}
}