如何使用泛型在 Java 中编写 LRU 缓存?

简介: 【8月更文挑战第22天】

LRU(最近最少使用)缓存是一种数据结构,它存储最近最少使用的元素,并在缓存已满时淘汰最旧的元素。使用泛型可以让你创建可存储任何类型对象的 LRU 缓存。

实现

以下是如何在 Java 中使用泛型实现 LRU 缓存:

import java.util.HashMap;
import java.util.Map;

public class LRUCache<K, V> {
   

    private final int capacity;
    private final Map<K, Node<K, V>> cache;
    private Node<K, V> head;
    private Node<K, V> tail;

    public LRUCache(int capacity) {
   
        this.capacity = capacity;
        this.cache = new HashMap<>();
    }

    public V get(K key) {
   
        Node<K, V> node = cache.get(key);
        if (node == null) {
   
            return null;
        }
        moveToHead(node);
        return node.value;
    }

    public void put(K key, V value) {
   
        Node<K, V> node = cache.get(key);
        if (node != null) {
   
            node.value = value;
            moveToHead(node);
            return;
        }
        node = new Node<>(key, value);
        cache.put(key, node);
        addToHead(node);
        if (cache.size() > capacity) {
   
            removeTail();
        }
    }

    private void moveToHead(Node<K, V> node) {
   
        if (node == head) {
   
            return;
        }
        if (node == tail) {
   
            tail = tail.prev;
            tail.next = null;
        } else {
   
            node.prev.next = node.next;
            node.next.prev = node.prev;
        }
        node.next = head;
        node.prev = null;
        head = node;
    }

    private void addToHead(Node<K, V> node) {
   
        if (head == null) {
   
            head = tail = node;
            return;
        }
        node.next = head;
        head.prev = node;
        head = node;
    }

    private void removeTail() {
   
        if (tail == null) {
   
            return;
        }
        cache.remove(tail.key);
        if (tail == head) {
   
            head = tail = null;
            return;
        }
        tail = tail.prev;
        tail.next = null;
    }

    private static class Node<K, V> {
   
        K key;
        V value;
        Node<K, V> prev;
        Node<K, V> next;

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

用法

以下是如何使用此 LRU 缓存:

LRUCache<String, Integer> cache = new LRUCache<>(3);

cache.put("key1", 1);
cache.put("key2", 2);
cache.put("key3", 3);

System.out.println(cache.get("key1")); // 输出:1
cache.put("key4", 4);

System.out.println(cache.get("key2")); // 输出:null

结论

使用泛型可以让你创建可存储任何类型对象的 LRU 缓存。这使得缓存更灵活,可以用于各种场景。

目录
相关文章
|
2月前
|
缓存 JavaScript 前端开发
Java 如何确保 JS 不被缓存
【10月更文挑战第19天】在 Java 中,可以通过设置 HTTP 响应头来确保 JavaScript 文件不被浏览器缓存。方法包括:1. 使用 Servlet 设置响应头,通过 `doGet` 方法设置 `Expires`、`Cache-Control` 和 `Pragma` 头;2. 在 Spring Boot 中配置拦截器,通过 `NoCacheInterceptor` 类和 `WebConfig` 配置类实现相同功能。这两种方法都能确保每次请求都能获取到最新的 JavaScript 内容。
|
2月前
|
缓存 算法 数据挖掘
深入理解缓存更新策略:从LRU到LFU
【10月更文挑战第7天】 在本文中,我们将探讨计算机系统中缓存机制的核心——缓存更新策略。缓存是提高数据检索速度的关键技术之一,无论是在硬件还是软件层面都扮演着重要角色。我们会详细介绍最常用的两种缓存算法:最近最少使用(LRU)和最少使用频率(LFU),并讨论它们的优缺点及适用场景。通过对比分析,旨在帮助读者更好地理解如何选择和实现适合自己需求的缓存策略,从而优化系统性能。
66 3
|
2月前
|
Java API
[Java]泛型
本文详细介绍了Java泛型的相关概念和使用方法,包括类型判断、继承泛型类或实现泛型接口、泛型通配符、泛型方法、泛型上下边界、静态方法中使用泛型等内容。作者通过多个示例和测试代码,深入浅出地解释了泛型的原理和应用场景,帮助读者更好地理解和掌握Java泛型的使用技巧。文章还探讨了一些常见的疑惑和误区,如泛型擦除和基本数据类型数组的使用限制。最后,作者强调了泛型在实际开发中的重要性和应用价值。
47 0
[Java]泛型
|
2月前
|
存储 安全 Java
🌱Java零基础 - 泛型详解
【10月更文挑战第7天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
20 1
|
3月前
|
Java 编译器 容器
Java——包装类和泛型
包装类是Java中一种特殊类,用于将基本数据类型(如 `int`、`double`、`char` 等)封装成对象。这样做可以利用对象的特性和方法。Java 提供了八种基本数据类型的包装类:`Integer` (`int`)、`Double` (`double`)、`Byte` (`byte`)、`Short` (`short`)、`Long` (`long`)、`Float` (`float`)、`Character` (`char`) 和 `Boolean` (`boolean`)。包装类可以通过 `valueOf()` 方法或自动装箱/拆箱机制创建。
47 9
Java——包装类和泛型
|
2月前
|
Java 语音技术 容器
java数据结构泛型
java数据结构泛型
28 5
|
2月前
|
存储 Java 编译器
Java集合定义其泛型
Java集合定义其泛型
20 1
|
2月前
|
存储 Java 编译器
【用Java学习数据结构系列】初识泛型
【用Java学习数据结构系列】初识泛型
23 2
|
2月前
|
缓存 分布式计算 NoSQL
大数据-47 Redis 缓存过期 淘汰删除策略 LRU LFU 基础概念
大数据-47 Redis 缓存过期 淘汰删除策略 LRU LFU 基础概念
82 2
|
3月前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)