手写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);
    }
}
相关推荐
哦虎!4 小时前
【JavaEE】网络初识
java
for_ever_love__5 小时前
MySQL ORDER BY 排序优化:从 Using filesort 到索引有序扫描(含双路 / 单路排序原理)
java·mysql·优化·存储·by·order·filesort
我是人✓6 小时前
Java文件上传三方式对比:从传统到SpringBoot
java·开发语言
欣栀♡6 小时前
JVM 频繁 Full GC 先看日志括号里的 cause,jstat 的 FGC 在 JDK 8 上会骗人
java·jvm
IT研究室6 小时前
最新计算机毕业设计选题推荐-基于spring boot的葡萄酒文化宣传网站-网站-文档指导-Java-springboot
java·spring boot·课程设计
慧都小项6 小时前
MyEclipse 中创建和测试 JAX-RS REST 接口:从项目配置到 REST Explorer
java·restful·myeclipse·jax-rs
Wang's Blog6 小时前
Java 项目实战: 交友项目 - 入门案例:编写 Dubbo 服务提供者
java·dubbo·交友
秋饼7 小时前
Spring AI 2.0 结构化输出企业级实战:从 BeanOutputConverter 源码到生产级解析容错
java·ai·技术分享·后端开发
摇滚侠7 小时前
《计算机是如何工作的:人人都能懂的计算机软硬件工作原理》第 9 章 机器码与汇编语言 阅读笔记 9
java·开发语言·笔记
Cc.Y7 小时前
Java零基础入门:深入Java核心:文件IO与序列化全解
java·开发语言·python