//设计一个类似于LFU 和LRU 的缓存 优化 算法 可以变更的缓存结构
public class Cache {
//首先自己定义缓存优化算法的基本的数据结构以及操作缓存的方法
//设计具有双指针的结点
public class Node<V>{
public V value;
public Node<V>last;
public Node<V>next;
public Node(V value){
this.value=value;
}
}
//设计的双端队列结构
public class NodeDoubleLinKList<V>{
private Node<V>head;
private Node<V>tail;
public NodeDoubleLinKList(){
this.head=head;
this.tail=tail;
}
//添加结点到尾部的逻辑逻辑
public void addNode(Node<V>newNode){
if(newNode==null){
return;
}
//说明双端链表中只有一个结点 ,那么让头结点的指针和尾结点指针指向该结点即可
if(head==newNode){
this.head=newNode;
this.tail=newNode;
}else {
newNode.last=this.tail;
this.tail.next=newNode;
this.tail=newNode;
}
}
//移动结点到尾部的逻辑
public void moveNodeToTail(Node<V>node){
//如果当前结点就是尾结点,直接返回
if(this.tail==node){
return;
}
if(this.head==node){
//head指针重定向
this.head=node.next;
this.head.last=null;
}else{
//解放指向node的指针
node.last.next=node.next;
node.next.last=node.last;
}
//node指针重定向
node.last=this.tail;
node.next=null;
this.tail.next=node;
this.tail=node;
}
//移除头结点的逻辑
public Node<V>removeHead(){
if(head==null){
return null;
}
Node<V>res=head;
//如果双端链表中只有一个结点
if(this.head==this.tail){
this.tail=null;
this.head=null;
}else {
//head的指针指向重定向
this.head=res.next;
res.next=null;
this.head.last=null;
}
return res;
}
}
//缓存优化算法的具体实现逻辑
//把记录之间按照访问的频率进行划分
//就是上面自己定义的NodeDoubleLinkList
//一旦加入新的记录,就把该纪录加到NodeDoubleLinkedList的尾部(addNdoe)
//一旦获得(get)或者设置(set)一个key,就将这个key对应的node在NodeDoubleLinkList中调整到尾部(moveNodToTail),一旦cache满了就删除最不经常使用的记录(removeHead)
//为了能够让每一个key都能在双端链表中找到对应的结点
public class MyCache<K,V>{
private HashMap<K, Node<V>>keyNodeMap;
private HashMap<Node<V>,K>nodeKeyMap;
private NodeDoubleLinKList<V>nodeList;
private int capacity;
public MyCache(int capacity){
if(capacity<1){
throw new RuntimeException("should be more than 0");
}
this.keyNodeMap=new HashMap<K, Node<V>>();
this.nodeKeyMap=new HashMap<Node<V>, K>();
this.nodeList=new NodeDoubleLinKList();
this.capacity=capacity;
}
public V get(K key){
if(this.keyNodeMap.containsKey(key)){
Node<V>resNode=this.keyNodeMap.get(key);
this.nodeList.moveNodeToTail(resNode);
return resNode.value;
}
return null;
}
public void set (K key,V value){
if(this.keyNodeMap.containsKey(key)){
Node<V>node=this.keyNodeMap.get(key);
node.value=value;
this.nodeList.moveNodeToTail(node);
}else{
Node<V>newNode=new Node<V>(value);
this.keyNodeMap.put(key, newNode);
this.nodeKeyMap.put(newNode,key );
this.nodeList.addNode(newNode);
if(this.keyNodeMap.size()==this.capacity+1){
this.removeMostUnusedCache();
}
}
}
//清理缓存空间
private void removeMostUnusedCache() {
Node<V>removeNode=this.nodeList.removeHead();
K removeKey=this.nodeKeyMap.get(removeNode);
this.nodeKeyMap.remove(removeNode);
this.keyNodeMap.remove(removeKey);
}
//这里执行缓存缓存 如果在web环境下也可以 在web.xml中定义ServletContextListener 来监听执行你的定时任务
// 如果你用spring,那么你不需要写Timer类了,在schedulingContext-timer.xml 中进行配置就可以了
//org.springframework.scheduling.timer.ScheduledTimerTask
public class ListByDayTimerTask extends TimerTask{
@Override
public void run() {
removeMostUnusedCache();
}
}
//定时清除缓存
public void Timingexecution(){
Timer timer=new Timer();
timer.schedule(new ListByDayTimerTask(),10000,86400000);
}
}
}