java实现lru缓存

什么是LRU缓存? (What is LRU Cache?)

LRU Cache stands for Least Recently Used Cache. The size of the cache is fixed and it supports get() and put() operations. When the cache is full, the put() operation removes the least recently used cache.

LRU缓存代表“最近最少使用的缓存”。 缓存的大小是固定的,并且支持get()和put()操作。 当缓存已满时,put()操作将删除最近最少使用的缓存。

如何在Java中实现LRU Cache? (How to implement LRU Cache in Java?)

The LRU cache can be implemented in Java using two data structures – HashMap and a doubly-linked list to store the data.

LRU高速缓存可以使用两个数据结构-HashMap和一个用于存储数据的双向链接列表来用Java实现。

The idea is to always have the elements in the following order.

想法是始终按以下顺序排列元素。

Least Recently Used (LRU) -> A <-> B <-> C <-> D <-> E <- Most Recently Used (MRU)最近使用最少(LRU)-> A <-> B <-> C <-> D <-> E <-最近使用(MRU)

Here is the LRUCache implementation in Java.

这是Java中的LRUCache实现。

package com.journaldev.examples;import java.util.HashMap;
import java.util.Map;public class LRUCache<K, V> {private Node<K, V> lru;private Node<K, V> mru;private Map<K, Node<K, V>> container;private int capacity;private int currentSize;public LRUCache(int capacity) {this.capacity = capacity;this.currentSize = 0;lru = new Node<K, V>(null, null, null, null);mru = lru;container = new HashMap<K, Node<K, V>>();}public V get(K key) {Node<K, V> tempNode = container.get(key);if (tempNode == null) {return null;}// If MRU leave the list as it iselse if (tempNode.key == mru.key) {return mru.value;}// Get the next and prev nodesNode<K, V> nextNode = tempNode.next;Node<K, V> prevNode = tempNode.prev;// If at the left-most, we update LRUif (tempNode.key == lru.key) {nextNode.prev = null;lru = nextNode;}// If we are in the middle, we need to update the items before and after our// itemelse if (tempNode.key != mru.key) {prevNode.next = nextNode;nextNode.prev = prevNode;}// Finally move our item to the MRUtempNode.prev = mru;mru.next = tempNode;mru = tempNode;mru.next = null;return tempNode.value;}public void put(K key, V value) {if (container.containsKey(key)) {return;}// Put the new node at the right-most end of the linked-listNode<K, V> myNode = new Node<K, V>(mru, null, key, value);mru.next = myNode;container.put(key, myNode);mru = myNode;// Delete the left-most entry and update the LRU pointerif (currentSize == capacity) {container.remove(lru.key);lru = lru.next;lru.prev = null;}// Update container size, for the first added entry update the LRU pointerelse if (currentSize < capacity) {if (currentSize == 0) {lru = myNode;}currentSize++;}}// Node for doubly linked listclass Node<T, U> {T key;U value;Node<T, U> prev;Node<T, U> next;public Node(Node<T, U> prev, Node<T, U> next, T key, U value) {this.prev = prev;this.next = next;this.key = key;this.value = value;}}}

Some important points about the implementation.

有关实施的一些重要点。

  • The Node class is used to implement doubly linked list structure. It has references to the previous and next node.Node类用于实现双向链表结构。 它具有对上一个和下一个节点的引用。
  • When we are getting a value using the get() method, the element is moved to the rightmost position because it becomes MRU element.当我们使用get()方法获取值时,该元素将移动到最右边的位置,因为它成为MRU元素。
  • When we are putting an element in the cache, it’s added to the rightmost side. If the container is full, then the LRU element is removed.当我们将元素放入缓存时,它会添加到最右侧。 如果容器已满,则将删除LRU元素。
  • We are using Generics so that we can use the implementation with any types of data.我们正在使用泛型,以便我们可以将实现与任何类型的数据一起使用。

LRUCache测试程序 (LRUCache Test Program)

I am using JUnit test cases to run some scenarios from the LeetCode question.

我正在使用JUnit测试用例来运行LeetCode问题中的某些方案。

package com.journaldev.examples;import static org.junit.jupiter.api.Assertions.assertEquals;import org.junit.jupiter.api.Test;class LRUCacheTest {private LRUCache<Integer, Integer> c;public LRUCacheTest() {this.c = new LRUCache<>(2);}@Testpublic void testCacheStartsEmpty() {assertEquals(c.get(1), null);}@Testpublic void testSetBelowCapacity() {c.put(1, 1);assertEquals(c.get(1), 1);assertEquals(c.get(2), null);c.put(2, 4);assertEquals(c.get(1), 1);assertEquals(c.get(2), 4);}@Testpublic void testCapacityReachedOldestRemoved() {c.put(1, 1);c.put(2, 4);c.put(3, 9);assertEquals(c.get(1), null);assertEquals(c.get(2), 4);assertEquals(c.get(3), 9);}@Testpublic void testGetRenewsEntry() {c.put(1, 1);c.put(2, 4);assertEquals(c.get(1), 1);c.put(3, 9);assertEquals(c.get(1), 1);assertEquals(c.get(2), null);assertEquals(c.get(3), 9);}}

LRUCache Test

LRUCache测试

结论 (Conclusion)

There are many ways to implement LRU Cache. But, if we keep the cache elements in the order of their usage, then we can get better performance in the put() operation.

有很多方法可以实现LRU缓存。 但是,如果我们按照缓存元素的使用顺序进行排序,则可以在put()操作中获得更好的性能。

参考资料 (References)

  • StackOverflow QuestionStackOverflow问题
  • Quora DiscussionQuora讨论

翻译自: https://www.journaldev.com/32688/lru-cache-implementation-in-java

java实现lru缓存

java实现lru缓存_Java中的LRU缓存实现相关推荐

  1. java中缓冲区和缓存_Java中的Google协议缓冲区

    java中缓冲区和缓存 总览 协议缓冲区是一种用于结构化数据的开源编码机制. 它是由Google开发的,旨在实现语言/平台中立且可扩展. 在本文中,我的目的是介绍Java平台上下文中协议缓冲区的基本用 ...

  2. java io流顶层_Java中的IO流(一)

    一,IO流的分类 A,按照操作的对象不同可分为字节流与字符流 B,按照流的方向不同可分为输入(指从外部存储设备拿文件到内存)流也叫读与输出(指从内存把文件写入到外部存储设备)流也叫写 注:字节流可以操 ...

  3. java 文件流 重写_java中关于文件流的总结

    [File类] 1. 作用: 用于对磁盘文件进行操作. 删除.创建等. 2. 三种常用的构造函数: ① File file1 = new File("F:\\test"); 直接传 ...

  4. java堆和客栈_JAVA中堆、栈,静态方法和非静态方法的速度问题

    一.堆和栈的速度性能分析 堆和栈是JVM内存模型中的2个重要组成部分,自己很早以前也总结过堆和栈的区别,基本都是从存储内容,存储空间大小,存储速度这几个方面来理解的,但是关于堆和栈的存储速度,只知道堆 ...

  5. java volatile 基本类型_Java中Volatile关键字详解(转)

    一.基本概念 先补充一下概念:Java 内存模型中的可见性.原子性和有序性. 可见性: 可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉.通常,我们无法确保执行读操作的线程能适时地看到其 ...

  6. java多线程 线程安全_Java中的线程安全

    java多线程 线程安全 Thread Safety in Java is a very important topic. Java provides multi-threaded environme ...

  7. java 自动过期缓存_Java自动过期本地缓存简单实现

    实际项目中常常需要用到本地缓存,特别是一些固定不变的数据,不想频繁调接口,因为http请求本身需要耗时,下面几个类对本地缓存作了简单实现,支持自动过期功能 LocalCache.javainterfa ...

  8. java可以多重继承吗_Java中的多重继承与组合vs继承

    java可以多重继承吗 有时我写了几篇有关Java继承,接口和组成的文章. 在这篇文章中,我们将研究多重继承,然后了解组成优于继承的好处. Java中的多重继承 多重继承是创建具有多个超类的单个类的能 ...

  9. java中有没有栈_Java中堆和栈有什么区别

    stack 和 heep 都是内存的一部分stack 空间小,速度比较快, 用来放对象的引用heep 大,一般所有创建的对象都放在这里.栈(stack):是一个先进后出的数据结构,通常用于保存方法(函 ...

最新文章

  1. 什么叫做类数组对象?
  2. 云南省2021高考成绩排名查询,2020年云南高考成绩位次排名及一分一段表查询
  3. 后台数据到mysql怎样保持实时更新_京东智联云MySQL数据库如何保障数据的可靠性?...
  4. tfrecord可以以列表的形式传入多个路径
  5. foreach循环怎么获取全部返回值_JavaScript中For循环的3种版本和使用场景
  6. 采用信号量机制实现消费者与生产者的线程同步_你还能聊聊常用的进程同步算法? 上篇[五]...
  7. Android Library projetcts cannot be exported.
  8. nlp自然语言处理_自然语言处理(NLP):不要重新发明轮子
  9. oracle 导出空表问题
  10. C++ 上用 ONNXruntime 部署自己的模型
  11. 数字电子技术逻辑运算
  12. 定时任务cron表达式详解
  13. VMware 镜像安装
  14. web系统变慢了,怎么排查原因
  15. 油相CdSe/ZnS量子点溶液 硒化镉/硫化锌量子点介绍及阐述
  16. 数据分析师,你是车夫,还是拉车的驴子
  17. double转换为二进制
  18. redis做浏览历史数据
  19. 【Mathematica】 最小二乘法
  20. 19.2. /etc/shells

热门文章

  1. javascript HTML静态页面传值的四种方法
  2. webservice helloworld案例
  3. 转 《pywinauto进行win32应用程序的测试》
  4. [转载] python中@property和property函数使用
  5. [转载] Python str方法
  6. verilog之状态机的结构
  7. java基本语法(运算符)
  8. 跳一跳外挂的python实现--OpenCV步步精深
  9. 解决移动端遮罩层无法覆盖全部页面问题
  10. EBS R12.2 创建应用层的启动和关闭脚本