public class LFUcacheTest {
/**
* 一个缓存结构需要实现如下功能
* void set(key,value) 加入或修改key对应的value
* int get(key) 查询对应的value的值
* 缓存中最多放K条记录,如果新的第K+1条记录加入,就需要根据策略删掉一条记录,然后把新记录加入
* 策略:在缓存结构的K条记录中,哪一个key从进入缓存结构的时刻开始,被调用set或get的次数最少,就删掉这个key记录
* 如果调用次数最少的key有多个,上次调用发生最早的key被删除
*/
public static void main(String[] args) {
LFUcache<String,String> cache = new LFUcache<>(3);
cache.set("1", "1");
cache.set("2", "2");
cache.set("3", "3");
cache.get("1");
cache.set("4", "4");
cache.set("5", "5");
// cache.set("5", "05");
System.out.println(cache.get("1"));
}
}
class Node<T> {
public T value;
public int times = 1;//调用次数
public Node<T> pre;
public Node<T> next;
public Node(T value) {
this.value = value;
}
}
class NodeList<T> {
public Node<T> head;
public Node<T> tail;
public NodeList<T> pre;
public NodeList<T> next;
public int times = 1;//调用次数
public void addHead(Node<T> node) {
if(head == null) {
this.head = node;
this.tail = node;
}else {
this.head.pre = node;
node.next = this.head;
this.head = node;
}
}
}
class LFUcache<K,T>{
//容量
public int capacity;
//当前存储数量
public int size;
//存储 key - node
Map<K,Node<T>> nodeMap;
//存储 node - nodeList
Map<Node<T>,NodeList<T>> nodeListMap;
//存储 node - key
Map<Node<T>,K> nodeKeyMap;
//存储第一次添加的次数为1的调用
NodeList<T> head;
public LFUcache(int capacity) {
this.capacity = capacity;
this.nodeMap = new HashMap<>();
this.nodeListMap = new HashMap<>();
this.nodeKeyMap = new HashMap<>();
}
public void set(K key, T value) {
//先判断是否已存在该key
Node<T> node = nodeMap.get(key);
if(node !=null) {
node.value = value;
node.times = node.times+1;
NodeList<T> nodeList = nodeListMap.get(node);
Node<T> pre = node.pre;
Node<T> next = node.next;
if(pre !=null && next !=null) {
pre.next = next;
next.pre = pre;
}
if(pre == null && next !=null) {
nodeList.head = next;
next.pre = null;
}
if(pre !=null && next == null) {
nodeList.tail = pre;
pre.next = null;
}
if(pre == null && next == null) {
nodeList.head = null;
nodeList.tail = null;
}
node.pre = null;
node.next = null;
NodeList<T> nodeListNext = nodeList.next;
if(nodeListNext == null) {
nodeListNext = new NodeList<>();
nodeListNext.times = nodeList.times +1;
nodeListNext.addHead(node);
nodeListMap.put(node, nodeListNext);
nodeListNext.pre = nodeList;
nodeList.next = nodeListNext;
}else if(nodeListNext.times == nodeList.times +1) {
nodeListNext.addHead(node);
nodeListMap.put(node, nodeListNext);
nodeListNext.pre = nodeList;
nodeList.next = nodeListNext;
}else {//说明调用次数不是连续的
NodeList<T> nodeListMiddle = new NodeList<>();
nodeListMiddle.times = nodeList.times +1;
nodeListMiddle.addHead(node);
nodeList.next = nodeListMiddle;
nodeListMiddle.pre = nodeList;
nodeListMiddle.next = nodeListNext;
nodeListNext.pre = nodeListMiddle;
nodeListMap.put(node, nodeListMiddle);
}
}else {
this.size++;
if(this.size>this.capacity) {
//缓存已满需要清空 调用次数最少的key
Node<T> lastNode = this.head.tail;
K k = this.nodeKeyMap.remove(lastNode);
this.nodeMap.remove(k);
NodeList<T> rmNodeList = this.nodeListMap.remove(lastNode);
Node<T> pNode = lastNode.pre;
if(pNode != null) {
this.head.tail = pNode;
pNode.next = null;
}else {
//当前nodeList 中没有 node了 清除它
NodeList<T> nextHeadList = this.head.next;
this.head = nextHeadList;
if(nextHeadList !=null) {
nextHeadList.pre = null;
}
}
this.size--;
}
node = new Node<>(value);
nodeMap.put(key, node);
nodeKeyMap.put(node, key);
if(this.head == null) {
this.head = new NodeList<>();
}
if(this.head.times>1) {
NodeList<T> newHead = new NodeList<>();
newHead.next = this.head;
this.head.pre = newHead;
this.head = newHead;
}
this.head.addHead(node);
nodeListMap.put(node, this.head);
}
}
public T get(K key) {
Node<T> node = this.nodeMap.get(key);
if(node == null) {
return null;
}else {
node.times = node.times+1;
NodeList<T> nodeList = this.nodeListMap.get(node);
//原来的nodeList 移除node
Node<T> pre = node.pre;
Node<T> next = node.next;
if(pre !=null && next !=null) {
pre.next = next;
next.pre = pre;
}
if(pre == null && next !=null) {
nodeList.head = next;
next.pre = null;
}
if(pre !=null && next == null) {
nodeList.tail = pre;
pre.next = null;
}
if(pre == null && next == null) {
nodeList.head = null;
nodeList.tail = null;
//当前nodeList 中没有node 需要移除
NodeList<T> nodeListPre = nodeList.pre;
NodeList<T> nodeListNext = nodeList.next;
if(nodeListPre != null && nodeListNext !=null ) {
nodeListPre.next = nodeListNext;
nodeListNext.pre = nodeListPre;
}
if(nodeListPre == null && nodeListNext !=null) {
this.head = nodeListNext;
nodeListNext.pre = null;
}
if(nodeListPre != null && nodeListNext == null) {
nodeListPre.next = null;
}
if(nodeListPre == null && nodeListNext == null) {
this.head = null;
}
}
node.pre = null;
node.next = null;
//调用次数+1
NodeList<T> nodeListNext = nodeList.next;
if(nodeListNext == null) {
nodeListNext = new NodeList<>();
nodeListNext.times = nodeList.times + 1;
nodeListNext.addHead(node);
nodeListMap.put(node, nodeListNext);
nodeListNext.pre = nodeList;
nodeList.next = nodeListNext;
}else if(nodeListNext.times == nodeList.times + 1) {
nodeListNext.addHead(node);
nodeListMap.put(node, nodeListNext);
nodeListNext.pre = nodeList;
nodeList.next = nodeListNext;
}else {//说明调用次数不是连续的
NodeList<T> nodeListMiddle = new NodeList<>();
nodeListMiddle.times = nodeList.times +1;
nodeListMiddle.addHead(node);
nodeList.next = nodeListMiddle;
nodeListMiddle.pre = nodeList;
nodeListMiddle.next = nodeListNext;
nodeListNext.pre = nodeListMiddle;
nodeListMap.put(node, nodeListMiddle);
}
return node.value;
}
}
}