Java实现LRU
简介
LRU(Least Recent Used) 最近最少使用,是经常用在内存的调度算法,在内存不够的情况下,为了载入新内容,不断淘汰旧内容.
实现原理
使用HashMap 和 双向链表实现 LRU
HashMap的 put 和 get 都是接近O(1),用HashMap的vlaue指向双向链表的Node节点的Index.
双向链表在这里用来实现LRU存储,head代表头部,tail代表尾部.
- 当有新数据添加时,将其添加到链表的头部O(1)
- 访问链表的节点的时候也将其置与链表的头部O(1)
- -当添加新元素链表满了的时候,则将淘汰双向链表的尾部O(1)
代码
package src.LRU最近最少使用;
import src.SingleListNOHEAD.Link;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
class LinkNode {
String key;
int value;
LinkNode pre = null;
LinkNode next = null;
public LinkNode(LinkNode pre, LinkNode next) {
this.pre = pre;
this.next = next;
}
public LinkNode() {
}
}
public class LRU {
private HashMap<String, LinkNode> cache = new HashMap<>();
private int size;
private int capacity;
private LinkNode head, tail;
public LRU(int capacity) {
this.size = 0;
this.capacity = capacity;
head = new LinkNode();
tail = new LinkNode();
head.next = tail; // 连接首尾
tail.pre = head;
}
/** * 获取node的value * @param key * @return */
public int get(String key) {
LinkNode node = cache.get(key);
if (node == null) {
return -1; // //没有这条记录
}
this.moveToHead(node);
return node.value;
}
public void set(String key, int value) {
//判断key是否存在
LinkNode node = cache.get(key);
if (node == null) {
LinkNode newNode = new LinkNode();
newNode.key = key;
newNode.value = value;
cache.put(key, newNode);
// 添加
this.add(newNode);
++size;
if (size > capacity) {
// 获取到尾节点
LinkNode tail = this.popTail();
// 删除尾节点
this.cache.remove(tail.key);
--size;
}
} else {
node.value = value;
//将其移动到链表头部
this.moveToHead(node);
}
}
/** * TODO : 移动到节点下一个 * 先删除,再添加 * * @param node */
private void moveToHead(LinkNode node) {
this.removeNode(node);
this.add(node);
}
/** * 链表中添加新节点 * * @param node */
private void add(LinkNode node) {
node.pre = head;
node.next = head.next;
head.next.pre = node;
head.next = node;
}
private void removeNode(LinkNode node) {
LinkNode pre = node.pre;
LinkNode next = node.next;
pre.next = node.next;
next.pre = node.pre;
}
public LinkNode popTail() {
LinkNode res = tail.pre;
this.removeNode(res);
return res;
}
public void ToString() {
LinkNode node = head.next;
while (node != tail) {
System.out.println("key" + node.key + " " + "value" + node.value);
node = node.next;
}
}
public static void main(String[] args) {
LRU lru = new LRU(9);
lru.set("1", 1);
lru.set("2", 1);
lru.set("3", 1);
lru.set("4", 1);
lru.set("1", 1);
lru.ToString();
}
}