LRU=Least Recently Used 最近最少使用淘汰算法(首先淘汰最长时间未被使用的页面)
2. LRU和LinkedHashMap的联系
2.1 accessOrder属性
true则按照访问顺序安排迭代顺序; false则按照插入顺序来安排迭代顺序;
/**
* The iteration ordering method for this linked hash map:
* true for access-order, false for insertion-order.
*/
final boolean accessOrder;
2.2 构造方法
LinkedHashMap有一个构造方法, 可以传递一个参数accessOrder
, 设置为true, 可以直接调整迭代出的顺序, 最近常使用的, 会排到最后, 最不常使用的, 放到最前面, 如果size()撑爆, 就开始砍最前面使用少的; 达到LRU的效果;
/**
* 构造一个空的LinkedHashMap实例,该实例具有指定的初始容量、装载因子和排序模式。
*/
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
3. LRU的LinkedHashMap实现:
3.1 实现代码
package com.niewj.dsalg;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* LRU算法简单实现-通过 LinkedHashMap 来实现
* Created by niewj on 2020/8/15 8:51
*/
public class LRUCache<K, V> {
private final LinkedHashMap<K, V> cache;
public LRUCache(final int maxSize) {
this.cache = new LinkedHashMap<K, V>(16, 0.75F, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > maxSize;
}
};
}
public void put(K key, V value) {
this.cache.put(key, value);
}
public V get(K key) {
return this.cache.get(key);
}
public V remove(K key) {
return this.cache.remove(key);
}
public static void main(String[] args) {
LRUCache lruCache = new LRUCache(128);
for (int i = 0; i < 150; i++) {
lruCache.put(i + "", i);
if (i >= 127) {
// 如果大于容量, 我们遍历前128个里面能被5整除的所有数一遍; 最后检查map内容, 看被移除的是不是5/0结尾的会避免
for (int i1 = 0; i1 < i; i1++) {
if (i1 % 5 == 0) {
System.out.print(lruCache.get(i1 + "") + "\t");
}
}
System.out.println("-----------");
}
}
System.out.println(" -- 下面是打印出的cache中的数据");
System.out.println(lruCache.cache);
}
}
3.2 main方法的输出
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 135 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 135 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 135 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 135 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 135 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 135 140 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 135 140 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 135 140 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 135 140 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 135 140 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 135 140 145 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 135 140 145 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 135 140 145 -----------
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 135 140 145 -----------
-- 下面是打印出的cache中的数据
{28=28, 29=29, 31=31, 32=32, 33=33, 34=34, 36=36, 37=37, 38=38, 39=39, 41=41, 42=42, 43=43, 44=44, 46=46, 47=47, 48=48, 49=49, 51=51, 52=52, 53=53, 54=54, 56=56, 57=57, 58=58, 59=59, 61=61, 62=62, 63=63, 64=64, 66=66, 67=67, 68=68, 69=69, 71=71, 72=72, 73=73, 74=74, 76=76, 77=77, 78=78, 79=79, 81=81, 82=82, 83=83, 84=84, 86=86, 87=87, 88=88, 89=89, 91=91, 92=92, 93=93, 94=94, 96=96, 97=97, 98=98, 99=99, 101=101, 102=102, 103=103, 104=104, 106=106, 107=107, 108=108, 109=109, 111=111, 112=112, 113=113, 114=114, 116=116, 117=117, 118=118, 119=119, 121=121, 122=122, 123=123, 124=124, 126=126, 127=127, 128=128, 129=129, 131=131, 132=132, 133=133, 134=134, 136=136, 137=137, 138=138, 139=139, 141=141, 142=142, 143=143, 144=144, 146=146, 147=147, 148=148, 149=149, 0=0, 5=5, 10=10, 15=15, 20=20, 25=25, 30=30, 35=35, 40=40, 45=45, 50=50, 55=55, 60=60, 65=65, 70=70, 75=75, 80=80, 85=85, 90=90, 95=95, 100=100, 105=105, 110=110, 115=115, 120=120, 125=125, 130=130, 135=135, 140=140, 145=145}
可以看到, 28之前的所有元素都被清除了(除了我们访问过的5的倍数的元素), 可见最先插入的元素, 如果没有使用过, 等到满足条件 size() > maxSize
就会被清理;
核心就在于LinkedHashMap的@Override的方法removeEldestEntry:
public LRUCache(final int maxSize) {
this.cache = new LinkedHashMap<K, V>(16, 0.75F, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > maxSize;
}
};
}
4. LRU-LinkedHashMap小结
4.1 boolean字段accessOrder
4.2 三参构造方法
LinkedHashMap(initialCapacity, loadFactor, accessOrder)
4.3 重写removeEldestEntry方法
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > maxSize;
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 hi@niewj.com