Redis的LRU算法简介与实现

LRU算法简介

LRU是Least Recently Used的缩写,即最近最少使用,是一种常用的页面置换算法,选择最近最久没有使用的数据予以淘汰。

核心思想:哈希表+双向链表

实现一:利用LinkedHashMap

import java.util.LinkedHashMap;
public class LRUCache<K,V> extends LinkedHashMap<K, V>{
	
	private int capacity;  //缓存坑位
	
	
	public LRUCache(int capacity) {
		/**
	     * @param  Capacity the initial capacity
	     * @param  loadFactor      the load factor  装载因子,底层代码是0.75,这里写死,也写成0.75
	     * @param  accessOrder     the ordering mode - <tt>true</tt> for
	     *         access-order, <tt>false</tt> for insertion-order  访问顺序
	     */
		super(capacity,(float) 0.75,true);
		this.capacity = capacity;
	}

	@Override
	protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
		// TODO Auto-generated method stub
		return super.size()>capacity;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		LRUCache lru = new LRUCache<>(3);
		lru.put(1, "a");
		lru.put(2, "b");
		lru.put(3, "c");
		System.out.println(lru.keySet());
		lru.put(4, "d");
		System.out.println(lru.keySet());
		lru.put(3, "c");
		System.out.println(lru.keySet());
		lru.put(3, "c");
		System.out.println(lru.keySet());
		lru.put(3, "c");
		System.out.println(lru.keySet());
		lru.put(5, "x");
		System.out.println(lru.keySet());
		
	}

}

输出(这是在accessOrder也就是访问顺序为true的情况下的结果):

输出(这是在accessOrder也就是访问顺序为false的情况下的结果):

实现二:手写LRU,不依赖JDK

import java.util.HashMap;
import java.util.Map;

public class LRUCache{
	
	//1、构造一个Node节点作为数据载体
	class Node<K,V>{
		K key;
		V value;
		Node<K,V> prev;
		Node<K,V> next;
		public Node() {
			this.prev=this.next=null;
		}
		
		public Node(K key,V value) {
			this.key=key;
			this.value=value;
			this.prev=this.next=null;
		}
	}
	
	//2、构建一个双向链表,里面放的就是我们的Node
	class DoubleLinkedList<K,V>{
		Node<K,V> head;
		Node<K,V> tail;
		
		//2.1 构造方法
		public DoubleLinkedList() {
			head = new Node<>();
			tail = new Node<>();
			head.next = tail;
			tail.prev = head;
		}
		
		//2.2 添加到头
		
		public void addHead(Node<K,V> node) {
			node.next=head.next;
			node.prev=head;
			head.next.prev=node;
			head.next=node;
		}
		
		//2.3 删除节点
		public void removeNode(Node<K,V> node) {
			node.next.prev = node.prev;
			node.prev.next = node.next;
			node.prev=null;
			node.next=null;
		}
		
		//2.4  获得最后一个节点
		public Node getLast() {
			return tail.prev;
		}
	}
	
	private int cacheSize;
	Map<Integer,Node<Integer,Integer>> map;
	DoubleLinkedList<Integer, Integer> doubleLinkedList;
	
	public LRUCache(int cacheSize) {
		this.cacheSize = cacheSize;
		map = new HashMap<Integer, LRUCache.Node<Integer,Integer>>();
		doubleLinkedList = new DoubleLinkedList<>();
	}
	
	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;
	}
	
	public void put(int key,int value) {
		if(map.containsKey(key)) {
			//如果当前key已经存在map中,那么value的值要被覆盖掉
			Node<Integer,Integer> node = map.get(key);
			node.value = value;
			map.put(key, node);
			//同时删除添加进来的节点,然后将该节点放在最前面,表示最近访问过的节点
			doubleLinkedList.removeNode(node);
			doubleLinkedList.addHead(node);
		} else {
			if(map.size()==cacheSize) {
				//如果这个时候map的大小已经达到了定义的cacheSize,那么将最后一个节点删除
				Node<Integer,Integer> lastNode = doubleLinkedList.getLast();
				map.remove(lastNode.key);
				doubleLinkedList.removeNode(lastNode);
			}
			//新增一个node
			Node<Integer,Integer> node = new Node<>(key,value);
			map.put(key, node);
			doubleLinkedList.addHead(node);
		}
		
		//遍历一下doubleLinkedList  关系里面的key值顺序
		Node temp = doubleLinkedList.head.next;
		while(temp!=doubleLinkedList.tail) {
			System.out.print(temp.key+" ");
			temp=temp.next;
		}
		System.out.println();
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		LRUCache lru = new LRUCache(3);
		lru.put(1, 1);
		lru.put(2, 2);
		lru.put(3, 3);
		
		lru.put(4, 4);
		
		lru.put(3, 3);
		
		lru.put(3, 3);
		
		lru.put(3, 3);
		
		lru.put(5, 5);
	}
}

输出:

 

猜你喜欢

转载自blog.csdn.net/kidchildcsdn/article/details/114208122