package com.xiaoleilu.hutool.cache.impl;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Iterator;
/**
* LRU (least recently used)最近最久未使用缓存<br>
* 根据使用时间来判定对象是否被持续缓存<br>
* 当对象被访问时放入缓存,当缓存满了,最久未被使用的对象将被移除。<br>
* 此缓存基于LinkedHashMap,因此当被缓存的对象每被访问一次,这个对象的key就到链表头部。<br>
* 这个算法简单并且非常快,他比FIFO有一个显著优势是经常使用的对象不太可能被移除缓存。<br>
* 缺点是当缓存满时,不能被很快的访问。
* @author Looly,jodd
*
* @param <K> 键类型
* @param <V> 值类型
*/
public class LRUCache<K, V> extends AbstractCache<K, V> {
/**
* 构造<br>
* 默认无超时
* @param capacity 容量
*/
public LRUCache(int capacity) {
this(capacity, 0);
}
/**
* 构造
* @param capacity 容量
* @param timeout 默认超时时间
*/
public LRUCache(int capacity, long timeout) {
this.capacity = capacity;
this.timeout = timeout;
//链表key按照访问顺序排序,调用get方法后,会将这次访问的元素移至头部
cacheMap = new LinkedHashMap<K, CacheObj<K, V>>(capacity + 1, 1.0f, true){
private static final long serialVersionUID = -1806954614512571136L;
@Override
protected boolean removeEldestEntry(Map.Entry<K, CacheObj<K, V>> eldest) {
if(LRUCache.this.capacity == 0) {
return false;
}
//当链表元素大于容量时,移除最老(最久未被使用)的元素
return size() > LRUCache.this.capacity;
}
};
}
// ---------------------------------------------------------------- prune
/**
* 只清理超时对象,LRU的实现会交给<code>LinkedHashMap</code>
*/
@Override
protected int pruneCache() {
if (isPruneExpiredActive() == false) {
return 0;
}
int count = 0;
Iterator<CacheObj<K, V>> values = cacheMap.values().iterator();
CacheObj<K, V> co;
while (values.hasNext()) {
co = values.next();
if (co.isExpired()) {
values.remove();
onRemove(co.key, co.obj);
count++;
}
}
return count;
}
}