import java.util.Random;
/**
* 自己实现LRU
*/
public class MyLRUImpl<K, V> {
private int cap;
private int size = 0;
private Node<K, V> head;
private Node<K, V> tail;
private DB<K, V> db;
/**
* 设定容量,以及访问数据库的抽象工厂
* @param cap
* @param db
*/
public MyLRUImpl(int cap, DB<K, V> db) {
this.cap = cap;
this.db = db;
}
public V get(K key) {
if (key == null) {
throw new NullPointerException();
}
Node<K, V> temp = head;
Node<K, V> ahead = null;
while (temp != null) {
if (temp.key.equals(key)) {
if (temp.next != null) {
System.out.println("找到了匹配的缓存");
moveToTail(ahead, temp);
}
return temp.value;
}
ahead = temp;
temp = temp.next;
}
V newValue = getFromDB(key);
Node<K, V> newNode = new Node<>(key, newValue);
if (head == null) {
head = newNode;
tail = newNode;
}
tail.next = newNode;
tail = newNode;
size++;
checkCap();
return newValue;
}
private V getFromDB(K key) {
return db.getFromDB(key);
}
private void moveToTail(Node<K, V> ahead, Node<K, V> target) {
if (target == tail) {
return;
}
if (head == target) {
head = target.next;
tail.next = target;
tail = target;
} else {
ahead.next = target.next;
tail.next = target;
tail = target;
}
target.next = null;
}
public V put(K key, V value) {
if (key == null) {
throw new NullPointerException();
}
if (head == null) {
tail = head = new Node<>(key, value);
size++;
return null;
}
Node<K, V> temp = head;
while (temp != null) {
if (temp.key.equals(key)) {
V oldValue = temp.value;
temp.value = value;
System.out.println("进行了替换");
return oldValue;
}
temp = temp.next;
}
temp = new Node<>(key, value);
tail.next = temp;
tail = temp;
size++;
checkCap();
return null;
}
private void checkCap() {
if (size > cap) {
System.out.println("淘汰队首");
//进行淘汰,摘除开头
head = head.next;
size--;
}
}
public Node<K, V> peek() {
return head;
}
public void setCapacity(int capacity) {
throw new UnsupportedOperationException("无法再次设置容量");
}
public static class Node<K, V> {
K key;
V value;
Node<K, V> next;
Node(K key, V value) {
this.key = key;
this.value = value;
}
}
public static void main(String[] args) {
MyLRUImpl<String, String> lru = new MyLRUImpl<>(5, key -> String.valueOf(new Random().nextInt()));
lru.put("1", "1");//插入
lru.put("1", "2");//替换
lru.put("2", "2");//插入第二条
print(lru.peek());
lru.get("1");//查询,查看是否交换了顺序
System.out.println("查询1之后");print(lru.peek());
lru.get("3");//查询一个缓存中不存在的记录
System.out.println("查询3之后");print(lru.peek());
lru.get("4");
System.out.println("查询4之后");print(lru.peek());
lru.get("5");
System.out.println("查询5之后");print(lru.peek());
lru.get("6");//这时候开始淘汰了
System.out.println("查询6之后");print(lru.peek());
}
public static void print(Node head) {
while (head != null) {
System.out.println(head.key + " " + head.value);
head = head.next;
}
}
}
/**
* 抽象工厂,模拟缓存中找不到后在数据库中查询
*/
interface DB<K, V> {
V getFromDB(K key);
}