手写Redis淘汰策略中lru算法(删除最近未使用的值) java版
Posted 是Cc哈
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手写Redis淘汰策略中lru算法(删除最近未使用的值) java版相关的知识,希望对你有一定的参考价值。
1.题目描述:请见leetcode (LRU缓存机制)
2.实现思路:
通过HashMap + 双向链表实现
HashMap:保证查询的时间复杂度是O(1)
双向链表:链表特性,增删元素速度快,链表由头节点+中间节点+尾节点构成,每个节点有前节点和后节点,构成一个双向队列。
3.图解:
put方法:先判断当前节点数量是否等于设置的catchsize,
若等于,则删除tail节点的上一个节点,实现删除最长时间未使用的功能
若小于,再判断是否已经存在这个key了,
若存在,则修改value,再将这个节点放到head节点之后,删除原节点
若不存在,将增加的节点添加到head节点之后
get方法:先判断是否存在这个key
若不存在,返回-1
若存在,获取value值,并将该节点放到head节点之后,并删除原节点,这样做是为了表示该节点最近被使用过。
3.代码实现:
package com.chenchen.demo;
import java.util.HashMap;
import java.util.Map;
/**
* 手写LRU算法
* @author chenchen
*/
public class LRUCatchDemo
// Node节点
static class Node<K, V>
// key
K key;
// value
V value;
// 前节点
Node<K, V> prev;
// 后节点
Node<K, V> next;
public Node()
this.prev = null;
this.next = null;
public Node(K key, V value)
this.key = key;
this.value = value;
// 双向队列
class DoubleLinkedList<K, V>
// 头节点
Node<K, V> head;
// 尾节点
Node<K, V> tail;
DoubleLinkedList()
head = new Node<>();
tail = new Node<>();
this.head.next = this.tail;
this.tail.prev = this.head;
// 向队列中添加Node节点到头节点的下一个
public void addHead(Node<K, V> node)
node.next = this.head.next;
node.prev = this.head;
this.head.next.prev = node;
this.head.next = node;
// 向队列删除一个节点
public void removeNode(Node<K, V> node)
node.next.prev = node.prev;
node.prev.next = node.next;
node.prev = null;
node.next = null;
// 找出队列中最长时间未使用的节点
public Node<K, V> getLast()
return this.tail.prev;
// DoubleLinkedList的容量
private static int catchSize;
private static Map<Integer, Node<Integer, Integer>> map;
private static DoubleLinkedList<Integer,Integer> doubleLinkedList;
public LRUCatchDemo(int catchSize)
this.catchSize = catchSize;
map = new HashMap<>();
doubleLinkedList = new DoubleLinkedList<>();
// 获取get方法
public static int get(int key)
if (!map.containsKey(key))
return -1;
else
Node<Integer, Integer> node = map.get(key);
// 使用后,需将该节点放到头节点
doubleLinkedList.removeNode(node);
doubleLinkedList.addHead(node);
return node.value;
// 添加put方法
public static void put(Integer key, Integer value)
// 如果存在key则更新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
// 达到容量峰值,删除最久未使用的node
if (map.size() == catchSize)
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);
public static void main(String[] args)
LRUCatchDemo lRUCache = new LRUCatchDemo(2);
LRUCatchDemo.put(1, 1); // 缓存是 1=1
System.out.println(LRUCatchDemo.map.keySet());
LRUCatchDemo.put(2, 2); // 缓存是 1=1, 2=2
System.out.println(LRUCatchDemo.map.keySet());
System.out.println(LRUCatchDemo.get(1)); // 返回 1
LRUCatchDemo.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 1=1, 3=3
System.out.println(LRUCatchDemo.map.keySet());
System.out.println(LRUCatchDemo.get(2)); // 返回 -1 (未找到)
LRUCatchDemo.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 4=4, 3=3
System.out.println(LRUCatchDemo.map.keySet());
System.out.println(LRUCatchDemo.get(1)); // 返回 -1 (未找到)
System.out.println(LRUCatchDemo.get(3)); // 返回 3
System.out.println(LRUCatchDemo.map.keySet());
System.out.println(LRUCatchDemo.get(4)); // 返回 4
4.测试结果:
以上是关于手写Redis淘汰策略中lru算法(删除最近未使用的值) java版的主要内容,如果未能解决你的问题,请参考以下文章
redis前传自己手写一个LRU策略 | redis淘汰策略
redis前传自己手写一个LRU策略 | redis淘汰策略
redis前传自己手写一个LRU策略 | redis淘汰策略