java如何实现一个LRU(最近最少使用)缓存?

简介: 实现了一个LRU缓存,使用双向链表保持访问顺序,哈希表用于定位元素。Java代码中,`LRUCache`类包含容量、哈希表及链表头尾节点。`get`方法查哈希表,找到则移动至链表头并返回值,否则返回-1。`put`方法更新或插入节点,超出容量则移除最不常用节点。

要实现一个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方法首先检查哈希表中是否已存在指定的键,如果存在,则更新对应的节点的值,并将其移动到双向链表的头部;如果不存在,则创建一个新的节点,将其添加到哈希表和双向链表的头部。当添加新节点时,需要检查当前缓存的大小是否已达到容量上限,如果达到上限,则需要从双向链表的尾部移除最近最少使用的元素(即哈希表中对应的键),并从哈希表中删除该键。

相关文章
|
3天前
|
缓存 安全 Java
7张图带你轻松理解Java 线程安全,java缓存机制面试
7张图带你轻松理解Java 线程安全,java缓存机制面试
|
3天前
|
缓存 算法 Java
数据结构~缓存淘汰算法--LRU算法(Java的俩种实现方式,万字解析
数据结构~缓存淘汰算法--LRU算法(Java的俩种实现方式,万字解析
|
3天前
|
缓存 算法 前端开发
前端开发者必知的缓存淘汰策略:LRU算法解析与实践
前端开发者必知的缓存淘汰策略:LRU算法解析与实践
|
5天前
|
缓存 算法 Java
Java本地高性能缓存实践
本篇博文将首先介绍常见的本地缓存技术,对本地缓存有个大概的了解;其次介绍本地缓存中号称性能最好的Cache,可以探讨看看到底有多好?怎么做到这么好?最后通过几个实战样例,在日常工作中应用高性能的本地缓存。
|
5天前
|
缓存 算法
LRU(Least Recently Used)算法是一种常用的计算机缓存替换算法
【5月更文挑战第4天】LRU算法是基于页面使用频率的缓存策略,优先淘汰最近最久未使用的页面。实现可采用双向链表或数组,前者灵活,后者时间复杂度低。优点是利用时间局部性提高命中率,简单易实现;缺点是占用空间,对循环访问和随机访问场景适应性不佳。
31 0
|
5天前
|
缓存 NoSQL Java
17:缓存机制-Java Spring
17:缓存机制-Java Spring
41 5
|
5天前
|
存储 缓存 算法
面试遇到算法题:实现LRU缓存
V哥的这个实现的关键在于维护一个双向链表,它可以帮助我们快速地访问、更新和删除最近最少使用的节点,同时使用哈希表来提供快速的查找能力。这样,我们就可以在 O(1) 的时间复杂度内完成所有的缓存操作。哈哈干净利索,回答完毕。
|
5天前
|
存储 缓存 监控
构建高效的Java缓存策略
【4月更文挑战第18天】本文探讨了如何构建高效的Java缓存策略,强调缓存可提升系统响应和吞吐量。关键因素包括缓存位置、粒度、失效与更新策略、并发管理、序列化及选择合适库(如Ehcache、Guava Cache、Caffeine)。最佳实践包括明确需求、选择合适解决方案、监控调整及避免常见陷阱。缓存优化是一个持续过程,需根据需求变化不断优化。
|
5天前
|
缓存 NoSQL Java
使用Redis进行Java缓存策略设计
【4月更文挑战第16天】在高并发Java应用中,Redis作为缓存中间件提升性能。本文探讨如何使用Redis设计缓存策略。Redis是开源内存数据结构存储系统,支持多种数据结构。Java中常用Redis客户端有Jedis和Lettuce。缓存设计遵循一致性、失效、雪崩、穿透和预热原则。常见缓存模式包括Cache-Aside、Read-Through、Write-Through和Write-Behind。示例展示了使用Jedis实现Cache-Aside模式。优化策略包括分布式锁、缓存预热、随机过期时间、限流和降级,以应对缓存挑战。