设计一个LRU算法(最近最少移除)来实现缓存
思路:
- 使用双向链表 + HashMap 实现
- 采取尾插法,未达到存储上限就每次在加入到链表尾部
- 访问链表节点,就将对应链表节点移到尾部,保持尾节点数据最新
- 链表长度达到上限就删除头节点
代码:
public class LRUCache {
private Node head;
private Node end;
//存储上限
private int limit;
private HashMap<String, Node> hashMap;
public LRUCache(int limit) {
this.limit = limit;
this.hashMap = new HashMap<>();
}
//删除中间节点
public void remove(String key) {
Node tnode = hashMap.get(key);
removeNode(tnode);
hashMap.remove(key);
}
/**
* 删除节点
* @param node
*/
public String removeNode(Node node) {
//尾节点删除
if(node == end) {
end = end.pre;
} else if(node == head) {
//头结点删除
head = head.next;
} else {
//中间节点删除
node.pre.next = node.next;
node.next.pre = node.pre;
}
return node.key;
}
/**
* 尾部添加节点
* @param node
*/
private void addNode(Node node) {
//尾节点不为空
if(end != null) {
end.next = node;
node.pre = end;
node.next = null;
}
//初始化head 和 end
if(head == null) {
head = node;
}
end = node;
}
/**
* 刷新被访问节点位置
* @param node
*/
private void refreshNode(Node node) {
//访问的是尾节点
if(node == end) {
return;
}
removeNode(node);
addNode(node);
}
//插入
private void put(String key, String value) {
//先查有没有node存在指定的key
Node node = hashMap.get(key);
//不存在,初始化
if(node == null) {
if(hashMap.size() >= limit) {
String oldkey = removeNode(head);
hashMap.remove(oldkey);
}
node = new Node(key, value);
addNode(node);
hashMap.put(key, node);
} else {
//存在刷新node
node.value = value;
refreshNode(node);
}
}
public String get(String key) {
Node node = hashMap.get(key);
if(node == null) {
return null;
}
refreshNode(node);
return node.value;
}
public static void main(String[] args) {
LRUCache lc = new LRUCache(5);
lc.put("001", "用户1");
lc.put("002", "用户2");
lc.put("003", "用户3");
lc.put("004", "用户4");
lc.put("005", "用户5");
lc.get("001");
lc.put("002", "用户2更新");
System.out.println(lc.get("002"));
}
}
class Node {
public String key;
public String value;
public Node pre;
public Node next;
Node(String key, String value) {
this.key = key;
this.value = value;
}
}