public class Cache<K, V> {
class Node {
Node pre;
Node next;
K key;
V value;
}
private final HashMap<K, Node> nodeCache;
private int maxCapacity;
private Node first;
private Node last;
public Cache(int maxCapacity) {
this.nodeCache = new HashMap<>(maxCapacity);
this.maxCapacity = maxCapacity;
}
public void put(K k, V v) {
Node node = nodeCache.get(k);
if (node == null) {
if (nodeCache.size() >= maxCapacity) {
nodeCache.remove(last.key);
removeLast();
}
node = new Node();
node.key = k;
}
node.value = v;
freshFirst(node);
nodeCache.put(k, node);
}
public void remove(K k, V v) {
Node node = nodeCache.get(k);
if (node == null) {
return;
}
if (node.equals(last)) {
last = last.pre;
}
if (node.equals(first)) {
first = first.next;
}
if (node.next != null) {
node.next.pre = node.pre;
}
if (node.pre != null) {
node.pre.next = node.next;
}
nodeCache.remove(k);
}
private void freshFirst(Node node) {
if (first.equals(node)) {
return;
}
if (node.next != null) {
node.next.pre = node.pre;
}
if (node.pre != null) {
node.pre.next = node.next;
}
if (node.equals(last)) {
last = last.pre;
}
if (first == null || last == null) {
first = last = node;
return;
}
node.next = first;
first.pre = node;
first = node;
first.pre = null;
}
private void removeLast() {
if (last != null) {
last = last.pre;
if (last == null) {
first = null;
} else {
last.next = null;
}
}
}
}