今天参考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,若是超出容量限制,则将最不常使用的元素移除