最简单lru缓存及改进版本(java备忘)
/** * edit by wesir,source from net (http://zhwj184.iteye.com/blog/1523347); * threadSafe; * * just a simple LRU cache, more function for google ConcurrentLinkedMap * @param <K> * @param <V> */ public final class SimpleCache<K, V> extends LinkedHashMap<K, V> { private static final long serialVersionUID = -3923317621052085848L; private int maxCapacity; private ReentrantLock lock = new ReentrantLock(); public SimpleCache(int maxCapacity) { super((int)FloatMath.ceil(maxCapacity/0.75f)+2, 0.75f, true);// make it do not rehash ever, just make sure size() < threshold(threshold = initCapacity*loadfactor) this.maxCapacity = maxCapacity; } @Override protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) { return size() > this.maxCapacity; } @Override public V put(K key, V value) { lock.lock(); try { return super.put(key, value); } finally { lock.unlock(); } } @Override public V get(Object key) { lock.lock(); try { return super.get(key); } finally { lock.unlock(); } } }
改进版如下,改进功能:
1,增加可变缓存容量(resize方法).
2,增加替换时的回调处理(OnItemClear).
public final class SimpleLRUCache<K, V> { static final float DEFAULT_LOAD_FACTOR = 0.75f; private int cacheSize; private ReentrantLock lock = new ReentrantLock(); private LinkedHashMap<K,V> cacheMap = null; private OnItemClear<V> clearCallback = null; public SimpleLRUCache(int size) { this.cacheSize = size; initCache(); } public SimpleLRUCache(int size,OnItemClear<V> callback) { this.cacheSize = size; initCache(); this.clearCallback = callback; } public void setClearCallback(OnItemClear<V> callback){ this.clearCallback = callback; } @SuppressWarnings("serial") private void initCache(){ // make it do not rehash ever, just make sure size() < threshold(threshold = initCapacity*loadfactor) cacheMap = new LinkedHashMap<K,V>((int)FloatMath.ceil(cacheSize/DEFAULT_LOAD_FACTOR)+2, DEFAULT_LOAD_FACTOR, true){ @Override protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) { boolean bRemovable = size() > cacheSize; if(bRemovable && null != clearCallback){ clearCallback.onItemClear(eldest.getValue()); } return size() > cacheSize; } }; } public void resize(int newSize) { lock.lock(); try{ if(newSize == this.cacheSize){ return; } LinkedHashMap<K,V> oldCacheMap = cacheMap; this.cacheSize = newSize; initCache(); cacheMap.putAll(oldCacheMap); oldCacheMap.clear(); oldCacheMap = null; }finally { lock.unlock(); } } public V put(K key, V value) { lock.lock(); try { return cacheMap.put(key, value); } finally { lock.unlock(); } } public V get(Object key) { lock.lock(); try { return cacheMap.get(key); } finally { lock.unlock(); } } public void clear(){ if(null != clearCallback){ for(V value:cacheMap.values()){ clearCallback.onItemClear(value); } } cacheMap.clear(); } } public interface OnItemClear<K>{ public void onItemClear(K item); }