阅读本文大概需要 7 分钟。
来自:https://www.cnblogs.com/wyq178/p/11790015.html
LRU全称 "Least Recently Used",最近最少使用策略,判断最近被使用的时间,距离目前最远的数据优先被淘汰,作为一种根据访问时间来更改链表顺序从而实现缓存淘汰的算法,它是redis采用的淘汰算法之一。
redis还有一个缓存策略叫做LFU, 那么LFU是什么呢?
LFU是什么
LRU实现
/** * 节点 */
public static class Node implements Comparable<Node>{ //键
Object key; //值
Object value; /** * 访问时间 */
long time; /** * 访问次数 */
int count; public Node(Object key, Object value, long time, int count) { this.key = key; this.value = value; this.time = time; this.count = count;
} public Object getKey() { return key;
} public void setKey(Object key) { this.key = key;
} public Object getValue() { return value;
} public void setValue(Object value) { this.value = value;
} public long getTime() { return time;
} public void setTime(long time) { this.time = time;
} public int getCount() { return count;
} public void setCount(int count) { this.count = count;
}
@Override public int compareTo(Node o) { int compare = Integer.compare(this.count, o.count); //在数目相同的情况下 比较时间
if (compare==0){ return Long.compare(this.time,o.time);
} return compare;
}
}
public class LFU<K,V> { /** * 总容量 */
private int capacity; /** * 所有的node节点 */
private Map<K, Node> caches; /** * 构造方法
* @param size */
public LFU(int size) { this.capacity = size;
caches = new LinkedHashMap<K,Node>(size);
}
}
/** * 添加元素
* @param key
* @param value */
public void put(K key, V value) {
Node node = caches.get(key); //如果新元素
if (node == null) { //如果超过元素容纳量
if (caches.size() >= capacity) { //移除count计数最小的那个key
K leastKey = removeLeastCount();
caches.remove(leastKey);
} //创建新节点
node = new Node(key,value,System.nanoTime(),1);
caches.put(key, node);
}else { //已经存在的元素覆盖旧值
node.value = value;
node.setCount(node.getCount()+1);
node.setTime(System.nanoTime());
}
sort();
}
/** * 排序 */
private void sort() {
List<Map.Entry<K, Node>> list = new ArrayList<>(caches.entrySet());
Collections.sort(list, new Comparator<Map.Entry<K, Node>>() {
@Override public int compare(Map.Entry<K, Node> o1, Map.Entry<K, Node> o2) { return o2.getValue().compareTo(o1.getValue());
}
});
caches.clear(); for (Map.Entry<K, Node> kNodeEntry : list) {
caches.put(kNodeEntry.getKey(),kNodeEntry.getValue());
}
}
/** * 移除统计数或者时间比较最小的那个
* @return
*/
private K removeLeastCount() {
Collection<Node> values = caches.values();
Node min = Collections.min(values); return (K)min.getKey();
}
/** * 获取元素
* @param key
* @return
*/
public V get(K key){
Node node = caches.get(key); if (node!=null){
node.setCount(node.getCount()+1);
node.setTime(System.nanoTime());
sort(); return (V)node.value;
} return null;
}
测试
public static void main(String[] args) {
LFU<Integer, String> lruCache = new LFU<>(5);
lruCache.put(1, "A");
lruCache.put(2, "B");
lruCache.put(3, "C");
lruCache.put(4, "D");
lruCache.put(5, "E");
lruCache.put(6, "F");
lruCache.get(2);
lruCache.get(2);
lruCache.get(3);
lruCache.get(6);
//重新put节点3
lruCache.put(3,"C");
final Map<Integer, Node> caches = (Map<Integer, Node>) lruCache.caches;
for (Map.Entry<Integer, Node> nodeEntry : caches.entrySet()) {
System.out.println(nodeEntry.getValue().value);
}
}
LRU和LFU的区别以及LFU的缺点
总结
扫码加入技术交流群,不定时「送书」
推荐阅读:
x³+y³+z³=3第三组整数解是多少,这个58年难题被40万台电脑算出来了
---特别推荐---
特别推荐:一个新的优质的专注分享各种开源项目、工具和高效率软件的公众号,「Java轮子」,非常值得大家关注。
朕已阅