package com.lru;
import java.util.HashMap;import java.util.Map;
/** * @author lucas * @create 2021-08-11 20:14 * @description 手写lru算法的实现 */public class LRUCache {
//创建存储节点类,类似于节点node的数据载体,存储键值对
class Node<k, v> { k keys; v values; Node<k, v> prev; //前指针 Node<k, v> next; //后指针
public Node() { this.prev = null; this.next = null; }
//初始化指针 public Node(k keys, v values) { this.keys = keys; this.values = values; this.prev = this.next = null; } }
//2.创建一个双向的队列,存储一个个node节点,组成一个数据结构
class DoubleLinkedList<k, v> {
Node<k, v> head; Node<k, v> tail;
//双端队列的构造方法 public DoubleLinkedList() { this.head = new Node<k, v>(); this.tail = new Node<k, v>(); //头节点的下一个是尾节点,尾节点的前一个是头节点 head.next = tail; tail.prev = head; }
//添加到表头 public void addHeader(Node<k, v> node) {
/** * 将node放入表头 * 当前节点node的前节点-是当前节点(一个节点进入之后,新节点的下一个节点,head的下一个的位置) * 当前节点的前一个节点是头节点 */ node.next = head.next; node.prev = head;
/** * 头节点的下一个是尾节点,尾节点的前一个是node * 头节点的下一个是当前节点 */ head.next.prev = node; head.next = node;
}
//3删除node节点 public void removeNode(Node<k, v> node) {
/** * 删除当前节点 * 节点node的下一个节点是tail,之前节点,(删除前此节点的前一个节点) * 节点node的前一个节点head,之后的节点tail(删除前此节点的下一个节点) */ node.next.prev = node.prev; //head node.prev.next = node.next;
node.prev = null; node.next = null;
}
//获取尾节点数据 public Node getLast() { return tail.prev; }
}
private int cacheSize;
Map<Integer, Node<Integer, Integer>> dateMap;
DoubleLinkedList<Integer, Integer> doubleLinkedList;
//构造方法 public LRUCache(int cacheSize) { this.cacheSize = cacheSize; //查找 dateMap = new HashMap<>(); //排序,交换位置 doubleLinkedList = new DoubleLinkedList<>(); }
//缓存获取value值
public int get(int key) {
/** * 1.从map中取出数据,交换位置到表头,然后返回 * 2.取不到返回-1/ */ if (!dateMap.containsKey(key)) { return -1; } Node<Integer, Integer> dataNode = dateMap.get(key);
/** * 将队列中顺序,删除之前的位置node,添加到表头 */ doubleLinkedList.removeNode(dataNode); //将node添加到表头 doubleLinkedList.addHeader(dataNode);
return dataNode.values; }
//写操作或者是更新操作key public void put(int key, int value) {
/** * 三种情况: * 1.如果key存在,就更新操作 * 2.key不存在, 新增节点信息 * */
if (dateMap.containsKey(key)) { //更新节点的信息数据 Node<Integer, Integer> node = dateMap.get(key); node.values = value; dateMap.put(key, node); //加入队列表头 doubleLinkedList.removeNode(node); doubleLinkedList.addHeader(node);
} else { //是否达到最大容量了 if (dateMap.size() == cacheSize) {
Node lastNode = doubleLinkedList.getLast();
//获取到最末尾的节点数据,然后剔除map集合,剔除队列 dateMap.remove(lastNode.keys); doubleLinkedList.removeNode(lastNode); } /** * 新增操作 */ //重新加入node Node dateNode = new Node(key, value); dateMap.put(key, dateNode); //加入队列表头 doubleLinkedList.addHeader(dateNode); } }}
评论