手写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);
    }
}
相关推荐
接着奏乐接着舞。6 小时前
【2026】73道Redis 常见面试题与参考答案
数据库·redis·后端·缓存
程序员黎剑7 小时前
Spring-Bean生命周期-构造器访问Autowired字段为null
java·后端·spring
古法安卓7 小时前
Android-重启流程源码解析
android·java·android studio
清水白石0087 小时前
Python 类型设计深度解析:TypedDict 能否替代 dataclass?从 JSON 数据边界到 API 设计的最佳实践
java·python·json
晊晌_h8 小时前
嵌入式从0到精通——线程
java·开发语言·jvm
一木 之林8 小时前
五、C++ 新特性、关键字与编译原理(进阶)(二)
java·开发语言·c++
洋不写bug8 小时前
绕过权限检查,访问修改私有属性,反射,枚举,lambda
java·枚举·lambda·反射
evans在进步8 小时前
Java 常用设计模式入门:建造者、工厂、单例、外观与代理
java·python·设计模式
lisin-lee-cooper8 小时前
【leetcode658】有序数组找出k个最接近x的数
java·数据结构·算法
sunburn-8 小时前
Java堆(Heap)详解与实战教学
java·开发语言·数据结构·ide·算法