LFU缓存设计实现

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;
        }
    }
    
    
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值