一开始哨兵节点 dummy 的 prev 和 next 都指向 dummy。随着节点的插入,dummy 的 next 指向链表的第一个节点(最上面的书),prev 指向链表的最后一个节点(最下面的书)。
package com.yyb.juc.bagu;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
public class Lru_juc<K, V> {
private final int capacity;
private final Node<K, V> dummy;
private final ReentrantLock lock = new ReentrantLock();
private final Map<K, Node<K, V>> cache = new HashMap<>();
private int size = 0;
private static class Node<K, V> {
K key;
V value;
Node<K, V> next;
Node<K, V> prev;
Node(K key, V value) {
this.key = key;
this.value = value;
}
}
public Lru_juc(int capacity) {
if (capacity <= 0) {
throw new IllegalArgumentException("缓存容量必须大于0: " + capacity);
}
this.capacity = capacity;
dummy = new Node<>(null, null);
dummy.next = dummy;
dummy.prev = dummy;
}
public V get(K key) {
lock.lock();
try {
Node<K, V> node = cache.get(key);
if (node == null) {
return null;
}
moveToHead(node);
return node.value;
} finally {
lock.unlock();
}
}
public void put(K key, V value) {
lock.lock();
try {
Node<K, V> node = cache.get(key);
if (node != null) {
node.value = value;
moveToHead(node);
} else {
if (size >= capacity) {
Node<K, V> tail = dummy.prev;
cache.remove(tail.key);
removeNode(tail);
size--;
}
node = new Node<>(key, value);
addToHead(node);
cache.put(key, node);
size++;
}
} finally {
lock.unlock();
}
}
public int size() {
lock.lock();
try {
return size;
} finally {
lock.unlock();
}
}
public void clear() {
lock.lock();
try {
cache.clear();
dummy.next = dummy;
dummy.prev = dummy;
size = 0;
} finally {
lock.unlock();
}
}
private void moveToHead(Node<K, V> node) {
removeNode(node);
addToHead(node);
}
private void removeNode(Node<K, V> node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
private void addToHead(Node<K, V> node) {
node.prev = dummy;
node.next = dummy.next;
dummy.next.prev = node;
dummy.next = node;
}
}