【重温经典】LRU 缓存机制

rhino-3668126_640.jpg
在这里插入图片描述

需要一个哈希双端链表, D o u b l e L i n k e d N o d e DoubleLinkedNode DoubleLinkedNode

这个双端链表有下面的几个属性

        class DoubleLinkedNode {
            int key, value;//k,v
            DoubleLinkedNode pre, next;//前驱接节点,后继节点

            public DoubleLinkedNode(int key, int value) {
                this.key = key;
                this.value = value;
            }

            public DoubleLinkedNode() {
            }
        }

将新加入的节点插入到双端链表的头部位置 a d d F i r s t ( n o d e ) addFirst(node) addFirst(node)

image-20200904085250881.png

        /**
         * 将节点加入到双向链表的开头的位置
         */
        public void addFirst(DoubleLinkedNode node) {
            node.pre = head;//1.当前节点的前驱结点指向head节点
            node.next = head.next;//2.当前节点的后继节点指向head的后继节点

            head.next.pre = node;//3.head节点的后继节点的前驱结点指向当前节点
            head.next = node;//4.head的后继节点指向当前节点
        }

移除一个节点 r e m o v e N o d e ( n o d e ) removeNode(node) removeNode(node)

image-20200904090539191.png

        /**
         * 移除一个普通的节点
         *
         * @param node
         */
        public void removeNode(DoubleLinkedNode node) {
            DoubleLinkedNode next = node.next;
            DoubleLinkedNode pre = node.pre;
            pre.next = next;
            next.pre = pre;
        }

弹出最末尾的节点,并返回最后的节点 p o p L a s t popLast popLast

        /**
         * 弹出最末尾的节点并将改节点返回
         *
         * @return
         */
        public DoubleLinkedNode popLast() {
            DoubleLinkedNode last = tail.pre;
            removeNode(last);
            return last;
        }

将一个已经在链表中存在的节点移动到链表的开头 m o v e T o H e a d ( n o d e ) moveToHead(node) moveToHead(node)

  • 先移除这个节点移除,再将这个节点添加到链表的开头
        /**
         * 将当前节点移动到最头部位置
         *
         * @param node
         */
        public void moveToHead(DoubleLinkedNode node) {
            removeNode(node);
            addFirst(node);
        }

下面开始 L R U LRU LRU

思路

初始化

  • 注意 h e a d head head节点和 t a i l tail tail节点需要 n e w new new出来

g e t ( k e y ) get(key) get(key)

  • 如果 c a c h e cache cache中不存在 k e y key key,返回-1
  • 如果 c a c h e cache cache中存在,取出这个节点,将节点 m o v e T o H e a d moveToHead moveToHead,返回节点的值

p u t ( k , v ) put(k,v) put(k,v)

  • 取出节点,分节点存在与否讨论:
    • 节点不存在:新创建节点,将该节点插入到链表的头部,并将其 p u t put put c a c h e cache cache
      • 做一个额外的判断:如果当前的 c a c h e cache cache的大小大于 c a p a c i t y capacity capacity,需要移除最末尾的节点,链表和 c a c h e cache cache都要做移除操作
    • 节点存在:返回节点的值,将节点移动到链表头部
    class LRUCache {
        DoubleLinkedNode head, tail;//Node的收尾节点
        int capacity;//容量
        Map<Integer, DoubleLinkedNode> cache;//<k,v> k是key,v是key生成的node

        /**
         * 初始化
         *
         * @param capacity
         */
        public LRUCache(int capacity) {
            this.capacity = capacity;
            this.cache = new HashMap<>();
            this.head = new DoubleLinkedNode();
            this.tail = new DoubleLinkedNode();
            this.head.next = tail;
            this.tail.pre = head;

        }

        public int get(int key) {
            if (!cache.containsKey(key)) return -1;
            DoubleLinkedNode node = cache.get(key);
            moveToHead(node);
            return node.value;
        }

        public void put(int key, int value) {
            DoubleLinkedNode node = cache.get(key);
            if (node == null) {
                node = new DoubleLinkedNode(key, value);
                addFirst(node);
                cache.put(key, node);
                if (cache.size() > capacity) {
                    DoubleLinkedNode last = popLast();
                    cache.remove(last.key);
                }
            } else {
                node.value = value;
                moveToHead(node);
            }
        }
    }
更多内容,欢迎订阅
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值