LRU算法

LRU是什么?按照英文的直接原义就是Least Recently Used,最近最久未使用法,它是按照一个非常著名的计算机操作系统基础理论得来的:最近使用的页面数据会在未来一段时期内仍然被使用,已经很久没有使用的页面很有可能在未来较长的一段时间内仍然不会被使用。基于这个思想,会存在一种缓存淘汰机制,每次从内存中找到最久未使用的数据然后置换出来,从而存入新的数据!它的主要衡量指标是使用的时间,附加指标是使用的次数。在计算机中大量使用了这个机制,它的合理性在于优先筛选热点数据,所谓热点数据,就是最近最多使用的数据!因为,利用LRU我们可以解决很多实际开发中的问题,并且很符合业务场景

  1 import java.util.HashMap;
  2  
  3 public class LRU<K, V> {
  4     private int currentSize;//当前的大小
  5     private int capcity;//总容量
  6     private HashMap<K, Node> caches;//所有的node节点
  7     private Node first;//头节点
  8     private Node last;//尾节点
  9  
 10     public LRU(int size) {
 11         currentSize = 0;
 12         this.capcity = size;
 13         caches = new HashMap<K, Node>(size);
 14     }
 15  
 16     /**
 17      * 放入元素
 18      * @param key
 19      * @param value
 20      */
 21     public void put(K key, V value) {
 22         Node node = caches.get(key);
 23         //如果新元素
 24         if (node == null) {
 25             //如果超过元素容纳量
 26             if (caches.size() >= capcity) {
 27                 //移除最后一个节点
 28                 caches.remove(last.key);
 29                 removeLast();
 30             }
 31             //创建新节点
 32             node = new Node(key,value);
 33         }
 34         //已经存在的元素覆盖旧值
 35         node.value = value;
 36         //把元素移动到首部
 37         moveToHead(node);
 38         caches.put(key, node);
 39     }
 40  
 41     /**
 42      * 通过key获取元素
 43      * @param key
 44      * @return
 45      */
 46     public Object get(K key) {
 47         Node node = caches.get(key);
 48         if (node == null) {
 49             return null;
 50         }
 51         //把访问的节点移动到首部
 52         moveToHead(node);
 53         return node.value;
 54     }
 55  
 56     /**
 57      * 根据key移除节点
 58      * @param key
 59      * @return
 60      */
 61     public Object remove(K key) {
 62         Node node = caches.get(key);
 63         if (node != null) {
 64             if (node.pre != null) {
 65                 node.pre.next = node.next;
 66             }
 67             if (node.next != null) {
 68                 node.next.pre = node.pre;
 69             }
 70             if (node == first) {
 71                 first = node.next;
 72             }
 73             if (node == last) {
 74                 last = node.pre;
 75             }
 76         }
 77         return caches.remove(key);
 78     }
 79  
 80     /**
 81      * 清除所有节点
 82      */
 83     public void clear() {
 84         first = null;
 85         last = null;
 86         caches.clear();
 87     }
 88  
 89     /**
 90      * 把当前节点移动到首部
 91      * @param node
 92      */
 93     private void moveToHead(Node node) {
 94         if (first == node) {
 95             return;
 96         }
 97         if (node.next != null) {
 98             node.next.pre = node.pre;
 99         }
100         if (node.pre != null) {
101             node.pre.next = node.next;
102         }
103         if (node == last) {
104             last = last.pre;
105         }
106         if (first == null || last == null) {
107             first = last = node;
108             return;
109         }
110         node.next = first;
111         first.pre = node;
112         first = node;
113         first.pre = null;
114     }
115  
116     /**
117      * 移除最后一个节点
118      */
119     private void removeLast() {
120         if (last != null) {
121             last = last.pre;
122             if (last == null) {
123                 first = null;
124             } else {
125                 last.next = null;
126             }
127         }
128     }
129  
130     @Override
131     public String toString() {
132         StringBuilder sb = new StringBuilder();
133         Node node = first;
134         while (node != null) {
135             sb.append(String.format("%s:%s ", node.key, node.value));
136             node = node.next;
137         }
138         return sb.toString();
139     }
140      
141  
142     public static void main(String[] args) {
143         LRU<Integer, String> lru = new LRU<Integer, String>(5);
144         lru.put(1, "a");
145         lru.put(2, "b");
146         lru.put(3, "c");
147         lru.put(4,"d");
148         lru.put(5,"e");
149         System.out.println("原始链表为:"+lru.toString());
150  
151         lru.get(4);
152         System.out.println("获取key为4的元素之后的链表:"+lru.toString());
153  
154         lru.put(6,"f");
155         System.out.println("新添加一个key为6之后的链表:"+lru.toString());
156  
157         lru.remove(3);
158         System.out.println("移除key=3的之后的链表:"+lru.toString());
159     }
160 }
View Code

原始链表为:5:e 4:d 3:c 2:b 1:a

获取key为4的元素之后的链表:4:d 5:e 3:c 2:b 1:a
新添加一个key为6之后的链表:6:f 4:d 5:e 3:c 2:b
移除key=3的之后的链表:6:f 4:d 5:e 2:b

https://www.cnblogs.com/wyq178/p/9976815.html

原文地址:https://www.cnblogs.com/lingcheng7777/p/11677803.html