手写LRU 缓存

主要逻辑:

要有一个hashMap存储节点,实现o(1)的查找

要有一个双向链表,实现实现最近或刚添加的节点在头节点,

初始容量,每添加一个节点,就记录当前已添加的个数,如果添加之后已超过容量,则移除尾部的节点和hashMap里面的节点

java 复制代码
public class LRUCacheDemo {
    class LRUNode {
        private int key;
        private int value;
        private LRUNode prev;
        private LRUNode next;

        public LRUNode() {
        }

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

    private Map<Integer, LRUNode> cache = new HashMap<>();
    private int capacity;
    private int size;
    private LRUNode head, tail;

    public LRUCacheDemo(int capacity) {
        this.capacity = capacity;
        this.size = 0;
        head = new LRUNode();
        tail = new LRUNode();
        head.next = tail;
        tail.prev = head;
    }
    public int get(int key) {
        LRUNode lruNode = cache.get(key);
        if (lruNode == null) {
            return -1;
        }
        moveNodeToHead(lruNode);
        return lruNode.value;
    }
    public void put(int key, int value) {
        // 从缓存中查询,如果存在,则更新value, 并把对应的node移到头部
        LRUNode lruNode = cache.get(key);
        if (lruNode != null) {
            lruNode.value = value;
            moveNodeToHead(lruNode);
        } else {

            // 如果不存在,则直接插入

            // 放入hashMap
            LRUNode node = new LRUNode(key, value);
            cache.put(key, node);

            // 添加到双向链表的头部
            addToHead(node);
            size++;
            // 然后看容量是否超过了,如果超过了,则移除双向链表尾部的节点,并移除cache的节点
            if (size > capacity) {
                LRUNode tail = removeTail();
                cache.remove(tail.key);
                size--;

            }
        }


    }

    private LRUNode removeTail() {
        LRUNode tail = this.tail.prev;
        removeNode(tail);
        return tail;
    }

    private void moveNodeToHead(LRUNode lruNode) {
        removeNode(lruNode);
        addToHead(lruNode);
    }

    private void addToHead(LRUNode lruNode) {
        lruNode.prev = head;
        lruNode.next = head.next;
        head.next.prev = lruNode;
        head.next = lruNode;

    }

    private void removeNode(LRUNode lruNode) {
        lruNode.prev.next = lruNode.next;
        lruNode.next.prev =lruNode.prev;
    }

    public static void main(String[] args) {
        LRUCacheDemo lruCacheDemo = new LRUCacheDemo(2);
        lruCacheDemo.put(1,1);
        lruCacheDemo.put(2,2);
        lruCacheDemo.get(2);
        lruCacheDemo.put(3, 3);
        lruCacheDemo.put(4, 4);
        lruCacheDemo.get(1);
    }
}
相关推荐
jmxwzy8 分钟前
Redis
数据库·redis·缓存
北辰当尹9 分钟前
【实习之旅】Kali虚拟机桥接模式ping通百度
java·服务器·桥接模式
零叹11 分钟前
Redis热Key——大厂是怎么解决的
数据库·redis·缓存·热key
win x14 分钟前
Redis事务
数据库·redis·缓存
Just Dreamchaser14 分钟前
Pdf和Docx文件导出生成水印工具类
java·给pdf和docx文件添加水印
这个需求做不了16 分钟前
Java实现文件格式转换(图片,视频,文档,音频)
java
愿你天黑有灯下雨有伞21 分钟前
高性能Java并发编程:如何优雅地使用CompletableFuture进行异步编排
java
indexsunny22 分钟前
互联网大厂Java面试实战:基于电商场景的Spring Boot与微服务技术问答
java·spring boot·微服务·面试·hibernate·电商场景·技术问答
qq_124987075323 分钟前
基于Spring Boot的电影票网上购票系统的设计与实现(源码+论文+部署+安装)
java·大数据·spring boot·后端·spring·毕业设计·计算机毕业设计
无心水24 分钟前
【分布式利器:腾讯TSF】6、TSF可观测性体系建设实战:Java全链路Metrics+Tracing+Logging落地
java·分布式·架构·wpf·分布式利器·腾讯tsf·分布式利器:腾讯tsf