有这样一种业务,在一个很短时间内,有大量的请求进来,需要快速处理,但这些数据又不是很重要的不需要立马落库。这个时候就可以使用页面置换技术了。
1.首先我们需要一个节点类。这个节点类是一个双向链表
public class Node{
int key;
int value;
Node pre;
Node next;
public Node(){};
public Node(int key, int value) {
this.key = key;
this.value = value;
}
}
2.然后就是缓存类的具体实现啦。首先是该类需要的属性。
// 缓存的最大值
private int capacity;
// 当前存放的个数
private int size;
// 存储节点数据
private Map<Integer, Node> cache = new HashMap<>();
// 头结点
private Node head = null;
// 尾结点
private Node tail = null;
3.定义一个删除节点的方法,因为新增如果达到最大值的话,需要删除节点。
private void remove(Node node){
node.pre.next = node.next;
node.next.pre = node.pre;
}
4.定义一个新增到头结点的方法。
private void addHead(Node node){
// 当前节点的前一个节点指针执向头结点
node.pre = head;
// 当前指针的下一个节点指向头结点的下一个指针。
node.next = head.next;
// 头结点的下一个节点的前一个节点的指针指向当前节点
head.next.pre = node;
// 头结点的下一个指针指向当前节点
head.next = node;
}
5.设置一个移动到头结点的方法。就是删除节点,然后再新增到头结点上。
private void moveToHead(Node node){
remove(node);
addHead(node);
}
6.新增一个删除链表最后一个节点的办法。
private Node deleteTail(){
Node node = this.tail.pre;
remove(node);
return node;
}
7.接下来就是get方法了。方法的逻辑很简单,如果从hash表中找到了,就把他移动到头结点上,并返回,如果没找到直接返回。
public int get(int key){
Node node = cache.get(key);
if (node == null){
return -1;
}
moveToHead(node);
return node.value;
}
8.最后是put方法。
public void put(int key, int value){
// 看看节点是否已经存在。并把他加入到头结点。
Node node = cache.get(key);
if (node == null){
Node newNode = new Node(key, value);
cache.put(key, newNode);
addHead(newNode );
}else {
addHead(node);
}
// 容积加一
size++;
if (size > capacity){
// 如果已经到达最大值,需要把链表末尾的给他删了
Node tail = deleteTail();
cache.remove(tail);
size--;
}
}
接下来是完整代码
package com.springbootdome.springbootdome.algorithm.LRU;
import java.util.HashMap;
import java.util.Map;
/**
* @author xnl
* @Description: LRU实现
* @date: 2022/3/13 14:05
*/
public class Solution {
private int capacity;
private int size;
private Map<Integer, Node> cache = new HashMap<>();
private Node head = null;
private Node tail = null;
public Solution(int capacity){
this.size = 0;
this.capacity = capacity;
head = new Node();
tail = new Node();
head.next = tail;
tail.pre = head;
}
public int get(int key){
Node node = cache.get(key);
if (node == null){
return -1;
}
moveToHead(node);
return node.value;
}
public void put(int key, int value){
Node node = cache.get(key);
if (node == null){
Node newNode = new Node(key, value);
cache.put(key, newNode);
addHead(newNode);
}else {
addHead(node);
}
size++;
if (size > capacity){
Node tail = deleteTail();
cache.remove(tail);
size--;
}
}
private void addHead(Node node){
node.pre = head;
node.next = head.next;
head.next.pre = node;
head.next = node;
}
private void remove(Node node){
node.pre.next = node.next;
node.next.pre = node.pre;
}
private void moveToHead(Node node){
remove(node);
addHead(node);
}
private Node deleteTail(){
Node node = this.tail.pre;
remove(node);
return node;
}
public class Node{
int key;
int value;
Node pre;
Node next;
public Node(){};
public Node(int key, int value) {
this.key = key;
this.value = value;
}
}
}