LRU(Least Recently Used)算法,即最近最少使用算法,是置换算法(也叫淘汰算法)的一种,最早是在学习操作系统时接触的。
原理
当内存不足时,选择淘汰最久未使用的页面。
实现方法
实现方法有两种。
计时法
对于每个页面增加一个访问时间计时器。每当一个页面被访问时,当时的绝对时钟时间记录到被访问页面的计时器中;淘汰时,选取访问时间计时器中值最小的页面淘汰。
双向链表法(常用)
按照页面最后一次访问的时间次序将页面依次排列,最近被访问的页面排在队首,之前最久被访问的页面排在队尾。当一个页面被访问时,将这个页面排到队首;淘汰时,直接淘汰队尾那个最久未使用的页面即可。
LeetCode上实现LRU算法的题目:146. LRU 缓存。
- 使用Java JDK中封装的数据结构
LinkedHashMap
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class LRUCache extends LinkedHashMap<Integer, Integer> { private int capacity;
public LRUCache(int capacity) { super(capacity, 0.75f, true); this.capacity = capacity; }
public int get(int key) { return super.getOrDefault(key, -1); }
public void put(int key, int value) { super.put(key, value); }
@Override protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) { return size() > capacity; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
| public static class LRUCache { private int capacity; private HashMap<Integer, Node> hashMap = new HashMap<>(); private int size; private Node head = new Node(); private Node tail = new Node();
public LRUCache(int capacity) { this.capacity = capacity; this.size = 0; head.next = tail; tail.pre = head; }
public int get(int key) { Node node = hashMap.get(key); if (node == null) { return -1; } moveNewestNode(node); return node.value; }
public void put(int key, int value) { Node node = hashMap.get(key); if (node == null) { node = new Node(key, value); hashMap.put(key, node); addNode(node); } else { node.value = value; moveNewestNode(node); return; } if (size > capacity) { removeEldestNode(tail.pre); } }
private void addNode(Node node) { node.next = head.next; head.next.pre = node; node.pre = head; head.next = node; size++; }
private void moveNewestNode(Node node) { Node pre = node.pre, next = node.next; if (pre != null && next != null) { pre.next = next; next.pre = pre; } node.next = head.next; head.next.pre = node; node.pre = head; head.next = node; }
private void removeEldestNode(Node node) { Node pre = node.pre, next = node.next; pre.next = next; next.pre = pre; node.pre = null; node.next = null; hashMap.remove(node.key, node); size--; }
private class Node { private int key; private int value; private Node pre; private Node next; public Node() { } public Node(int key, int value) { this.key = key; this.value = value; } } }
|