java如何实现一个LRU(最近最少使用)缓存? 要求:设计一个LRU缓存,支持get和put操作。当缓存满时,需要淘汰最近最少使用的元素。要求使用双向链表+哈希表的数据结构来实现,并保证get和put操作的时间复杂度为O(1)。

简介: java如何实现一个LRU(最近最少使用)缓存?要求:设计一个LRU缓存,支持get和put操作。当缓存满时,需要淘汰最近最少使用的元素。要求使用双向链表+哈希表的数据结构来实现,并保证get和put操作的时间复杂度为O(1)。

要实现一个LRU缓存,可以使用双向链表和哈希表。双向链表用于存储缓存中的元素,按照访问顺序进行排序;哈希表用于快速查找元素在双向链表中的位置。

以下是Java代码实现:

import java.util.HashMap;

public class LRUCache {
   
    private int capacity;
    private HashMap<Integer, Node> map;
    private Node head;
    private Node tail;

    public LRUCache(int capacity) {
   
        this.capacity = capacity;
        map = new HashMap<>();
        head = new Node(-1, -1);
        tail = new Node(-1, -1);
        head.next = tail;
        tail.prev = head;
    }

    public int get(int key) {
   
        if (map.containsKey(key)) {
   
            Node node = map.get(key);
            remove(node);
            add(node);
            return node.value;
        }
        return -1;
    }

    public void put(int key, int value) {
   
        if (map.containsKey(key)) {
   
            Node node = map.get(key);
            node.value = value;
            remove(node);
            add(node);
        } else {
   
            if (map.size() >= capacity) {
   
                map.remove(tail.prev.key);
                remove(tail.prev);
            }
            Node newNode = new Node(key, value);
            map.put(key, newNode);
            add(newNode);
        }
    }

    private void add(Node node) {
   
        Node next = head.next;
        head.next = node;
        node.prev = head;
        node.next = next;
        next.prev = node;
    }

    private void remove(Node node) {
   
        Node prev = node.prev;
        Node next = node.next;
        prev.next = next;
        next.prev = prev;
    }

    class Node {
   
        int key;
        int value;
        Node prev;
        Node next;

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

在这个实现中,LRUCache类包含一个容量为capacity的哈希表map,以及两个指向双向链表头部和尾部的节点headtailget方法首先检查哈希表中是否存在指定的键,如果存在,则将对应的节点移动到双向链表的头部,并返回其值;否则返回-1。put方法首先检查哈希表中是否已存在指定的键,如果存在,则更新对应的节点的值,并将其移动到双向链表的头部;如果不存在,则创建一个新的节点,将其添加到哈希表和双向链表的头部。当添加新节点时,需要检查当前缓存的大小是否已达到容量上限,如果达到上限,则需要从双向链表的尾部移除最近最少使用的元素(即哈希表中对应的键),并从哈希表中删除该键。

相关文章
|
缓存 Java
Java本地高性能缓存实践问题之AsyncCache中移除一个缓存元素的问题如何解决
Java本地高性能缓存实践问题之AsyncCache中移除一个缓存元素的问题如何解决
334 0
|
缓存 Java
Java本地高性能缓存实践问题之使用Caffeine的Cache接口来查找一个缓存元素的问题如何解决
Java本地高性能缓存实践问题之使用Caffeine的Cache接口来查找一个缓存元素的问题如何解决
490 0
|
机器学习/深度学习 存储 缓存
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
文章主要介绍了排序算法的分类、时间复杂度的概念和计算方法,以及常见的时间复杂度级别,并简单提及了空间复杂度。
1068 1
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
|
数据库
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充
java数据结构,双向链表的实现
文章介绍了双向链表的实现,包括数据结构定义、插入和删除操作的代码实现,以及双向链表的其他操作方法,并提供了完整的Java代码实现。
java数据结构,双向链表的实现
|
canal 缓存 NoSQL
Redis常见面试题(一):Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;先删除缓存还是先修改数据库,双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
3126 6
Redis常见面试题(一):Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
|
Java
让星星⭐月亮告诉你,Java NIO之Buffer详解 属性capacity/position/limit/mark 方法put(X)/get()/flip()/compact()/clear()
这段代码演示了Java NIO中`ByteBuffer`的基本操作,包括分配、写入、翻转、读取、压缩和清空缓冲区。通过示例展示了`position`、`limit`和`mark`属性的变化过程,帮助理解缓冲区的工作原理。
353 2
|
存储 安全 Java
【用Java学习数据结构系列】探索顺序表和链表的无尽秘密(附带练习唔)pro
【用Java学习数据结构系列】探索顺序表和链表的无尽秘密(附带练习唔)pro
375 3
|
存储 Java
|
安全 Java 应用服务中间件
【Azure 应用服务】App Service中,为Java应用配置自定义错误页面,禁用DELETE, PUT方法
【Azure 应用服务】App Service中,为Java应用配置自定义错误页面,禁用DELETE, PUT方法
284 0
【Azure 应用服务】App Service中,为Java应用配置自定义错误页面,禁用DELETE, PUT方法