LRU算法实现, 参考LinkedHashMap
直接上代码
package LRUCache;
import java.util.HashMap;
import java.util.Map;
/**
* @author RYH
* @description lru算法, 参考linkedHashmap
* @date 2022/2/21
**/
public class LRUCacheDemo<K, V> {
/**
* 容量
*/
private final int capacity;
/**
* 用来存放key和节点, 方便快速查找
*/
Map<Integer, Node<Integer, Integer>> map;
/**
* 用来存放各个数据节点
*/
Node.DoubleLinkedList<Integer, Integer> doubleLinkedList;
public LRUCacheDemo(int capacity) {
this.capacity = capacity;
map = new HashMap<>();
doubleLinkedList = new Node.DoubleLinkedList<>();
}
/**
* 获取数据
* <p>
* 如果数据被使用, 则需要更新数据位置
*
* @param key 数据key
* @return 存放的value
*/
public int get(int key) {
if (!map.containsKey(key)) {
return -1;
}
Node<Integer, Integer> node = map.get(key);
doubleLinkedList.removeNode(node);
doubleLinkedList.addHead(node);
return node.value;
}
/**
* 数据新增
* <p>
* 如果存在数据key,则更新相应的值(类似hashmap),并且更新数据位置,
* 如果不存在则新增,
*
* @param key 数据key
* @param value 数据值
*/
public void put(int key, int value) {
if (map.containsKey(key)) {
Node<Integer, Integer> node = map.get(key);
node.value = value;
map.put(key, node);
doubleLinkedList.removeNode(node);
doubleLinkedList.addHead(node);
} else {
if (map.size() == this.capacity) {
Node<Integer, Integer> last = doubleLinkedList.getLast();
map.remove(last.key);
doubleLinkedList.removeNode(last);
}
Node<Integer, Integer> node = new Node<>(key, value);
map.put(key, node);
doubleLinkedList.addHead(node);
}
}
/**
* 内部节点类 用于存放数据节点
*
* @param <K> key
* @param <V> value
*/
static class Node<K, V> {
K key;
V value;
Node<K, V> prev;
Node<K, V> next;
Node() {
this.prev = this.next = null;
}
Node(K key, V value) {
this.key = key;
this.value = value;
this.prev = this.next = null;
}
/**
* 内部双向链表
* 记录数据书否被更新, 数据被操作, 则数据移到队列头部
*
* @param <K>
* @param <V>
*/
static class DoubleLinkedList<K, V> {
Node<K, V> head;
Node<K, V> tail;
public DoubleLinkedList() {
head = new Node<>();
tail = new Node<>();
head.next = tail;
tail.prev = head;
}
/**
* 向链表头部插入数据
*
* @param node 数据节点
*/
public void addHead(Node<K, V> node) {
node.next = head.next;
node.prev = head;
head.next.prev = node;
head.next = node;
}
/**
* 移除链表数据
*
* @param node 数据节点
*/
public void removeNode(Node<K, V> node) {
node.prev.next = node.next;
node.next.prev = node.prev;
node.prev = null;
node.next = null;
}
/**
* 获取数据最后一个节点
*
* @return 最后一个数据节点
*/
public Node<K, V> getLast() {
return tail.prev;
}
}
}
}