今天参考MyBatis框架对LruCache进行了一个简单的实现,LruCache,顾名思义,实现了Lru算法的缓存容器,
而Lru算法,则是当容器已满还要添加数据的时候,移除最近最不常使用的数据,保留最近最常使用的数据
以下是我参考MyBatis框架中的LruCache写的一个简单实现
1 package com.company.cache; 2 3 import java.util.LinkedHashMap; 4 import java.util.Map; 5 6 public class LruCache implements Cache { 7 private Cache cache; 8 private Map<Object, Object> map; 9 //定义一个变量来接收过时的Key 10 private Object oldKey; 11 public LruCache(Cache cache) { 12 this.cache = cache; 13 setSize(3); 14 } 15 public void setSize(final int maxCap){ 16 //使用匿名内部类继承LinkedHashMap来实现Lru算法,同时限定Cache大小 17 map = new LinkedHashMap<Object, Object>(maxCap, 0.75f, true){ 18 private static final long serialVersionUID = 2574527887416129186L; 19 20 /** 21 * 重写LinkedHashMap中的removeEldestEntry方法 22 * 这个方法在LinkedHashMap每次put时都会自动调用 23 * 重写之后,当存放数据时,map的数据量大于指定的容量的话, 24 * 就会把最不常使用的key赋值给我们在LruCache中定义的oldKey, 25 * 同时map删除这个key 26 * @param eldest 27 * @return 28 */ 29 @Override 30 protected boolean removeEldestEntry(java.util.Map.Entry<Object, Object> eldest) { 31 boolean b = size() > maxCap; 32 if(b){ 33 oldKey = eldest.getKey(); 34 } 35 return b; 36 } 37 }; 38 } 39 @Override 40 public void putObject(Object key, Object value) { 41 cache.putObject(key, value); 42 //调用在类中定义的私有方法 43 checkObject(key); 44 } 45 //当外部调用LruCache的getObject方法时,内部调用map的get方法以控制访问顺序 46 @Override 47 public Object getObject(Object key) { 48 map.get(key); 49 return cache.getObject(key); 50 } 51 //移除元素的同时,map移除对应的key 52 @Override 53 public Object removeObject(Object key) { 54 map.remove(key); 55 return cache.removeObject(key); 56 } 57 @Override 58 public String toString() { 59 return cache.toString(); 60 } 61 //检测oldKey是否为null,若是不为null的话则移除oldKey及对应的值,并把oldKey初始化为null 62 private void checkObject(Object key){ 63 map.put(key, key); 64 if(oldKey != null){ 65 cache.removeObject(oldKey); 66 oldKey = null; 67 } 68 }
内存的Lru算法实际上是基于LinkedHashMap来实现的,以LinkedHashMap来控制访问顺序,用内部封装的cache来存放数据,当put相同元素和get时,将该元素的访问量+1,若是超出容量限制,则将最不常使用的元素移除