单向链表设计LRU缓存
来源:互联网 发布:大数据公共服务平台 编辑:程序博客网 时间:2024/06/06 01:55
LRU是Least Recently Used的缩写,即最近最久未使用,常用于页面置换算法,是为虚拟页式存储管理服务的。常见的实现是将最近访问过的资源【引用】放一个队列,每次将新访问的放在队首,这样最不常用的就被放到队尾,当达到一定数量后,队尾的对象就被清除。缓存的应用场景很多,尤其是高并发的环境中,可以用来控制request数量。现在以一个单项链表为例,解释下如何来实现一个LRU。
新建一个单向链表
public final class Node{ String key; String value; Node next; public Node(){}; public void deleteLastNode(Node previous) { if(this.next == null) { previous.next = this.next; }else{ this.next.deleteLastNode(this); } }}
final修饰类,表示此类不能再被继承。
LRUCache的实现
一个LRU cacheList需要有一个长度和头节点,且需要实现get和set方法。对于set方法,每次添加一个元素的时候,除了将这个元素放在头节点,如果这个元素已经在cacheList里面,那么需要找出来并删除。
public class LRUCache{ private int size; private Node cacheList; public LRUCache(int size){ this.size = size; } public String get(String key){ Node currentNode = cacheList; if(key.isEmpty()){ return null; } while(currentNode.key != null){ if(currentNode.key == key){ return currentNode.value; }else{ currentNode = currentNode.next; } } return null; } public void set(String key, String value){ if(!key.isEmpty()){ int count = 0; Node newNode = new Node(); newNode.key = key; newNode.value = value; newNode.next = cacheList; cacheList = newNode; while(newNode.next != null){ if(newNode.next.key == key){ newNode.next = newNode.next.next; break; }else{ count ++; newNode = newNode.next; } } if(count >= size -1){ this.cacheList. deleteLastNode(this.cacheList); } } } private void printkeys() { int count = 0; Node currentNode = this.cacheList; while(currentNode != null){ System.out.println("Key-Value pair-" + count + ": " + currentNode.key + " " + currentNode.value); count ++; currentNode = currentNode.next; } }}
现在来测试一下:
public static void main(String[] args){ LRUCache testcache = new LRUCache(5); testcache.set("A", "A-VALUE"); testcache.set("B", "B-VALUE"); testcache.set("B", "B-VALUE"); testcache.set("C", "C-VALUE"); testcache.set("D", "D-VALUE"); testcache.set("E", "E-VALUE"); testcache.set("F", "F-VALUE"); testcache.printkeys();}
结果如下:
几个难点
理解链表的复制
cacheList = newNode;
cacheList被赋予了newNode的值,cacheList就记下了newNode的当前值,当newNode再次改变时,cacheList不会改变。
单向链表的节点删除
巧妙利用this来遍历指定节点。注意,这个方法要定义在Node class里面而不是在LRUCache类中。public void deleteLastNode(Node previous) { if(this.next == null) { previous.next = this.next; }else{ this.next.deleteLastNode(this); } }
另外一种方法可以用来删除任意节点的key:
public void deleteNode(String key) { if(cacheList.key.equals(key)) { if(cacheList.next != null) { cacheList= cacheList.next; }else{ cacheList = null; } }else { cacheList.next.delete(this.cacheList, key); }}
在Node类里面就要定义这个方法:
public void delete(Node previous, String key){ if(this.key.equals(key)) { previous.next = this.next; }else { if(this.next != null) { this.next.delete(this, key); } }}
阅读全文
0 0
- 单向链表设计LRU缓存
- LRU缓存设计
- LRU缓存设计
- 设计LRU缓存
- LRU缓存设计
- LRU缓存算法设计
- 缓存设计与 LRU
- LRU缓存策略设计
- LRU缓存策略设计
- LeetCode题解: LRU Cache 缓存设计
- Picasso中LRU缓存的设计分析
- 双向链表实现的简易缓存(LRU Cache)
- leetcode 146. LRU Cache 链表操作与缓存处理
- LRU缓存
- LRU缓存
- LRU缓存
- 缓存-LRU
- C++[类设计]单向链表
- 第一次躺上手术台
- 高并发,高性能,高可用,分布式,集群,电商缓存架构
- 回到顶部火箭demo
- 软件工程第二章第5题
- Oracle decode和nvl 函数的用法及区别?
- 单向链表设计LRU缓存
- 使用Xcode进行iOS设备无线调试
- 物体的移动与旋转
- docker入门简介
- 指令系统
- C++ 重写重载重定义区别
- python pickle/cPickle模块
- An error has occurred,See error log for more details 错误解决办法
- 对ListView的多条目的一些实现功能