LRU是一种缓存淘汰策略,全称是Least Recently Used,即最近最少使用,也就是说我们认为最近使用过的数据应该是是有用的,很久都没用过的数据应该是无用的。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。
LRU的实现思路就是hashmap+双链表,其中hashmap是为了加速查询, 双链表是为了保存使用状态,当一个缓存项被get, 这个缓存项会被移动到双向链表的头部。 当存储的缓存项超过了指定的capacity,则会从双链表的尾部进行移除。
Java已经自带了这种数据结构
1 package test1; 2 3 import java.util.LinkedHashMap; 4 import java.util.Map; 5 6 public class LRUCache { 7 8 private LinkedHashMap<Integer, Integer> map; 9 private final int CAPACITY; 10 11 public LRUCache(int capacity) { 12 CAPACITY = capacity; 13 map = new LinkedHashMap<Integer, Integer>(capacity, 0.75f, true) { 14 @Override 15 protected boolean removeEldestEntry(Map.Entry eldest) { 16 return size() > CAPACITY; 17 } 18 }; 19 } 20 21 public int get(int key) { 22 return map.getOrDefault(key, -1); 23 } 24 25 public void put(int key, int value) { 26 map.put(key, value); 27 } 28 }
package test1; import java.util.HashMap; import java.util.Map; public class MyLru<K, V> { private int capacity; private Node head; private Node tail; private Map<K, Node> map; public MyLru(int capacity) { this.capacity = capacity; this.map = new HashMap<>(8); } public void put(K k, V v) { // 如果链表为空 if (head == null) { head = new Node(k, v); tail = head; map.put(k, head); return; } Node node = map.get(k); // 如果存在,则提到链表开始, 并更新值 if (node != null) { node.value = v; removeToHead(node); } else { // 否则新建一个节点到开始 Node newNode = new Node(k, v); // 如果长度到了容量,需要去除结尾的节点 if (map.size() >= capacity) { System.out.println("移除末尾节点:[" + tail.key + "," + tail.value + "]"); map.remove(tail.key); tail = tail.prev; tail.next = null; } // 连到开始 map.put(k, newNode); head.prev = newNode; newNode.next = head; head = newNode; } } /** * 访问时,如果缓存有,则返回并把该节点放到最前面 */ public V get(K key) { Node node = map.get(key); if (node == null) { return null; } removeToHead(node); return node.value; } private void removeToHead(Node node) { if (node == head) { return; } else if (node == tail) { tail = node.prev; tail.next = null; } else { node.prev.next = node.next; node.next.prev = node.prev; } // set node to head node.next = head; head.prev = node; node.prev = null; head = node; } class Node { Node prev; Node next; K key; V value; public Node(K key, V value) { this.key = key; this.value = value; } } }
参考
https://jimolonely.github.io/2019/05/31/algorithm/003-lru-java/
原文:https://www.cnblogs.com/beyondbit/p/13222194.html