LRU(Least Recently Used),最近最少使用,是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰。该算法面试常备,本文以JAVA初级实现。
LRU详情参考 百度、Wiki
import java.util.HashMap;
import java.util.Map;
class LRUNode {
String key;
Object value;
LRUNode next;
LRUNode pre;
public LRUNode(String key, Object value) {
this.key = key;
this.value = value;
}
}
public class LRU {
//Initialize var
Map<String, LRUNode> map = new HashMap<>();
LRUNode head; //头指针
LRUNode tail; //尾指针
int capacity;
public LRU(int capacity) {
this.capacity = capacity;
}
//如果密钥不存在,则写入其数据值。当缓存容量达到上限时
//它应该在写入新数据之前删除最近最少使用的数据值,从而为新的数据值留出空间
public void put(String key, Object value) {
if (head == null) { // 如果为空,进行初始化
head = new LRUNode(key, value);
tail = head;
map.put(key, head);
}
LRUNode node = map.get(key);
if (node != null) { // 更新value,并将node移动到head
node.value = value;
removeAndInsert(node);
} else {
LRUNode tmp = new LRUNode(key, value);
if (map.size() >= capacity) { //删除尾节点
map.remove(tail);
tail = tail.pre;
tail.next = null;
}
map.put(key, tmp);
tmp.next = head;
head.pre = tmp;
head = tmp;
}
}
// 获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数)
public Object get(String key) {
LRUNode node = map.get(key);
if (node != null) {
removeAndInsert(node);
return node.value;
}
return null;
}
private void removeAndInsert(LRUNode node) { //删除节点,并插入头部
if (node == head) return; //如果原本为头指针,不需要操作
else if (node == tail) { //如果为尾指针,需把preNode.next设为null,tail标记为preNode
tail = node.pre;
tail.next = null;
} else { //中间指针将前指针.next设为当前指针的.next;同理后指针.pre
node.pre.next = node.next;
node.next.pre = node.pre;
}
// 将node指针插入头结点
node.next = head;
node.pre = null;
head.pre = node;
head = node;
}
}