35、链表-LRU缓存

思路:

        首先要了解LRU缓存的原理,首先定下容量,每次get请求和put请求都会把当前元素放最前/后面,如果超过容量那么头部/尾部元素就被移除,所以最近最少使用的元素会被优先移除,保证热点数据持续存在。 不管放在头部还是尾部都可以。看你怎么定义

        那么如何实现呢?有两种方式第一种直接继承LinkedHashMap 这个是已经帮我们实现的,代码如下:

class LRUCache extends LinkedHashMap<Integer, Integer>{private int capacity;public LRUCache(int capacity) {super(capacity, 0.75F, true);this.capacity = capacity;}public int get(int key) {return super.getOrDefault(key, -1);}// 这个可不写public void put(int key, int value) {super.put(key, value);}@Overrideprotected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {return size() > capacity; }
}

第二种就是手动去实现了,代码如下:

class LRUCache extends AbstractLRUCache<Integer, Integer> {public LRUCache(int capacity) {super(capacity);}public int get(int key) {Integer ans = super.get(key);return ans == null ? -1 : ans;}public void put(int key, int value) {super.set(key, value);}
}abstract class AbstractLRUCache<K, V> {private Map<K, Node<K, V>> keyNodeMap;private NodeDoubleLinkedList<K, V> nodeList;private final int capacity;public AbstractLRUCache(int cap) {if (cap < 1) {throw new RuntimeException("should be more than 0");}keyNodeMap = new HashMap<>();nodeList = new NodeDoubleLinkedList<>();capacity = cap;}public V get(K key) {if (keyNodeMap.containsKey(key)) {Node<K, V> res = keyNodeMap.get(key);nodeList.moveNodeToTail(res);return res.value;}return null;}public void set(K key, V value) {if (keyNodeMap.containsKey(key)) {Node<K, V> node = keyNodeMap.get(key);node.value = value;nodeList.moveNodeToTail(node);} else {Node<K, V> newNode = new Node<>(key, value);keyNodeMap.put(key, newNode);nodeList.addNode(newNode);if (keyNodeMap.size() == capacity + 1) {removeMostUnusedCache();}}}private void removeMostUnusedCache() {Node<K, V> node = nodeList.removeHead();keyNodeMap.remove(node.key);}class Node<K, V> {public K key;public V value;public Node<K, V> last;public Node<K, V> next;public Node(K key, V value) {this.key = key;this.value = value;}}class NodeDoubleLinkedList<K, V> {private Node<K, V> head;private Node<K, V> tail;public NodeDoubleLinkedList() {head = null;tail = null;}public void addNode(Node<K, V> newNode) {if (newNode == null) {return;}if (head == null) {head = newNode;tail = newNode;} else {tail.next = newNode;newNode.last = tail;tail = newNode;}}public void moveNodeToTail(Node<K, V> node) {if (this.tail == node) {return;}if (this.head == node) {this.head = node.next;this.head.last = null;} else {node.last.next = node.next;node.next.last = node.last;}node.last = this.tail;node.next = null;this.tail.next = node;this.tail = node;}public Node<K, V> removeHead() {if (this.head == null) {return null;}Node<K, V> res = this.head;if (this.head == this.tail) {this.head = null;this.tail = null;} else {this.head = res.next;res.next = null;this.head.last = null;}return res;}}
}

以下是代码实现的功能要点:

  1. AbstractLRUCache 是一个抽象类,它包含了 LRU 缓存的核心逻辑,如添加节点、移动节点到链表尾部、移除最少使用的节点等。

  2. LRUCache 是 AbstractLRUCache 的具体实现,它提供了 get 和 put 方法来与缓存进行交互。这些方法调用了抽象类中的方法来实现 LRU 逻辑。

  3. Node 类代表缓存中的一个条目,包含键、值以及指向前一个和后一个节点的指针。

  4. NodeDoubleLinkedList 是一个双向链表,用于按照访问顺序维护缓存中的节点。最近访问的节点被移动到链表的尾部,而最少使用的节点位于链表的头部。

  5. 当缓存达到其容量限制时,最少使用的节点(链表头部的节点)将被移除,以确保缓存大小不超过设定的容量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/624629.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【攻防世界】warmup

[HCTF 2018]WarmUp全网最详细解释_[hctf 2018]warmup的解-CSDN博客 php://filter 读取源码&#xff08;文件&#xff09; php://input 执行php代码&#xff0c;需要post请求提交数据 Content-Type为image/jpeg text. 绕过后缀的有文件格式有php,php3,php4,php5,pht…

SEO之搜索引擎的工作原理(三)

初创企业需要建站的朋友看这篇文章&#xff0c;谢谢支持&#xff1a;我给不会敲代码又想搭建网站的人建议 &#xff08;接上一篇。。。&#xff09; 排名 经过搜索引擎蜘蛛抓取页面&#xff0c;索引程序计算得到倒排索引后&#xff0c;搜索引擎就准备好可以随时处理用户搜索了…

java通过maven导入本地jar包的三种方式

一、引入lib下加载&#xff08;加载过后打包&#xff0c;以后再次使用不用再次导入&#xff09; 首先创建一个用于创建jar包的项目&#xff0c;并测试能否成功运行 讲项目打包 在需要引入的项目中创建lib目录 并把刚才打包的jar复制进去 通过dependency引入jar包 groupId、art…

【前后端的那些事】SpringBoot 基于内存的ip访问频率限制切面(RateLimiter)

文章目录 1. 什么是限流2. 常见的限流策略2.1 漏斗算法2.2 令牌桶算法2.3 次数统计 3. 令牌桶代码编写4. 接口测试5. 测试结果 1. 什么是限流 限流就是在用户访问次数庞大时&#xff0c;对系统资源的一种保护手段。高峰期&#xff0c;用户可能对某个接口的访问频率急剧升高&am…

【iOS】——SDWebImage源码学习

文章目录 一、SDWebIamge简介二、SDWebImage的调用流程SDWebImage源码分析1.UIImageViewWebCache层2.UIViewWebCache层3.SDWebManager层4.SDWebCache层5.SDWebImageDownloader层 一、SDWebIamge简介 SDWebImage是iOS中提供图片加载的第三方库&#xff0c;可以给UIKit框架中的控…

寄快递怕被骗?快来使用闪侠惠递寄快递避免这种麻烦!

我们去快递驿站寄快递的时候&#xff0c;总是快递的工作人员说是多少钱就要花费多少钱&#xff0c;这样不免会出现快递费高昂的局面&#xff0c;万一工作人员谎报了呢。那岂不是我们就要多花钱了呢&#xff0c;所以说究竟有没有一款寄快递的“神器”来便宜寄快递呢&#xff1f;…

有没有批量调节音乐播放速度的方法?调节音频的播放速度

一&#xff0c;引言​ 调节音乐播放的速度是一种有趣而富有创造性的方式&#xff0c;可以改变我们对音乐的感知和体验。通过调整音乐的速度&#xff0c;我们可以创造出全新的听觉效果&#xff0c;让音乐呈现出不同的情感和氛围。二&#xff0c;调节音乐速度的效果 调节音乐速…

《中医临床诊疗术语》数据库

最新版的《中医临床诊疗术语》于2023年3月17日由国家中医药管理局提出的&#xff0c;由国家市场监督管理总局和国家标准化管理委员会共同发布。新版的修订是为落实相关政策文件要求&#xff0c;推进中医医疗服务规范化、标准化管理&#xff0c;提高中医医疗服务标准化水平和管理…

【JavaScript】Promise 语法

前人栽树 许大仙 aexiar.github.io 前言 函数对象和实例对象 函数对象&#xff1a;将函数作为对象使用&#xff0c;简称为函数对象。实例对象&#xff1a;new 构造函数或类产生的对象&#xff0c;称为实例对象。 示例&#xff1a; <template> </template><s…

OpenHarmony实战开发-如何实现发布图片评论功能。

介绍 本示例将通过发布图片评论场景&#xff0c;介绍如何使用startAbilityForResult接口拉起相机拍照&#xff0c;并获取相机返回的数据。 效果图预览 使用说明 通过startAbilityForResult接口拉起相机&#xff0c;拍照后获取图片地址。 实现思路 1.创建CommentData类&…

【LatentDiffusion 代码详解(1)】LatentDiffusion 的 yaml 解读

YAML 文件提供了一种清晰、简洁且易于理解的方式来描述配置信息&#xff0c;特别适用于机器学习模型的超参数调优和实验管理。 以 Latent Diffusion 官方代码仓库中的 https://github.com/CompVis/latent-diffusion/blob/main/configs/autoencoder/autoencoder_kl_32x32x4.yam…

了解 Unity AI:从初学者到高级的综合指南

游戏中的AI是什么? 游戏中的人工智能是指利用人工智能技术使视频游戏中的非玩家角色和实体智能地行动、做出决策、对游戏环境做出反应,并提供引人入胜的动态游戏体验。什么是NPC? NPC 代表“非玩家角色”。NPC 是视频游戏、角色扮演游戏中不受人类玩家控制的角色。它们是计算…