package com.sf.test;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class LruCache<V> {
/**
* 容量
*/
private int capacity = 1024;
/**
* node 记录表
*/
private Map<String, ListNode<String, V>> table = new ConcurrentHashMap<>();
/**
* 双向链表头部
*/
private ListNode<String, V> head;
/**
* 双向链表尾部
*/
private ListNode<String, V> tail;
public LruCache(int capacity) {
this.capacity = capacity;
// 初始化 head 和 tail
head = new ListNode<>();
head.prev = null;
tail = new ListNode<>();
tail.next = null;
head.next = tail;
tail.prev = head;
}
/**
* 获取值,如果存在返回并且更新当前节点到链表头,不存在返回 null
* @param key
* @return
*/
public V get(String key) {
ListNode<String, V> node = table.get(key);
if (node == null) {
return null;
}
// 存在即移动 node 节点到表头
// 截断
node.prev.next = node.next;
node.next.prev = node.prev;
// 移动 node 到 head 后
node.next = head.next;
head.next.prev = node;
node.prev = head;
head.next = node;
// 存缓存表更新
table.put(key, node);
return node.value;
}
public void put(String key, V value) {
ListNode<String, V> node = table.get(key);
// 不存在代表缓存中没有
if (node == null) {
if (table.size() == capacity) {
// 超过容量,先移除尾节点前一个有效节点(head 和 tail 只是占位)
table.remove(tail.prev.key);
// 跳过删除的节点,进行对象绑定
tail.prev.prev.next = tail;
tail.prev = tail.prev.prev;
}
node = new ListNode<>();
node.key = key;
node.value = value;
// 更新
table.put(key, node);
}
// 移动 node 节点到表头
node.next = head.next;
head.next.prev = node;
node.prev = head;
head.next = node;
}
/**
* 双向链表内部类
* @param <K>
* @param <V>
*/
public static class ListNode<K, V> {
private K key;
private V value;
ListNode<K, V> prev;
ListNode<K, V> next;
public ListNode() {}
public ListNode(K key, V value) {
this.key = key;
this.value = value;
}
}
public static void main(String[] args) {
LruCache<ListNode<String, Integer>> cache = new LruCache<>(4);
ListNode<String, Integer> node1 = new ListNode<>("key1", 1);
ListNode<String, Integer> node2 = new ListNode<>("key2", 2);
ListNode<String, Integer> node3 = new ListNode<>("key3", 3);
ListNode<String, Integer> node4 = new ListNode<>("key4", 4);
ListNode<String, Integer> node5 = new ListNode<>("key5", 5);
cache.put("key1", node1);
cache.put("key2", node2);
cache.put("key3", node3);
cache.put("key4", node4);
System.out.println(cache.get("key2"));
cache.put("key5", node5); // 该操作会使得关键字 key1 作废 key5->key2->key4->key3
System.out.println(cache.get("key2"));
}
}
摘录:https://blog.csdn.net/qq_26440803/article/details/83795122 但是更新了部分代码,验证运行正常。