Java之简单LRU cache
利用一个 HashMap和 一个自己实现的简单循环双向链表实现的一个LRU原理的cache:
package SimpleCache; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import List.List; import List.ListNode; /*** * @category LRU策略的简单cache,基于HashMap + List实现 * @author xiaobaoqiu * @param K - key类型 * @param V - value类型 */ public class SimpleCache<K, V> { private Map<K, SimpleCache.CacheObject<V>> map = null; //map protected List accessedList = null; //访问列表 private int maxSize = 0; //最大容量 /* * 构造函数 */ public SimpleCache(int maxSize){ //怎么保证maxSize有效? if(maxSize <= 0){ maxSize = 1024; } this.maxSize = maxSize; this.map = new HashMap<K, SimpleCache.CacheObject<V>>(); this.accessedList = new List(); } /* * 当前size */ public int size() { return map.size(); } /* * 当前Capacity */ public long capacity() { return maxSize; } /* * 是否为空 */ public boolean isEmpty() { return map.isEmpty(); } /* * put操作,返回key原始对应的old value */ public synchronized V put(K key, V value){ V answer = remove(key); //删除key对应的已经存在项 SimpleCache.CacheObject<V> cacheObject = new SimpleCache.CacheObject<V>(value); map.put(key, cacheObject); ListNode lastAccessedNode = accessedList.addFirst(key); cacheObject.accessedNode = lastAccessedNode; cull(); //裁剪,使得大小不超 return answer; } /* * get操作,返回key对应的value */ public synchronized V get(Object key) { SimpleCache.CacheObject<V> cacheObject = map.get(key); if (cacheObject == null) { return null; } cacheObject.accessedNode.remove(); //删除自己 accessedList.addFirst(cacheObject.accessedNode); return cacheObject.value; } /* * 删除key对应的项 */ public synchronized V remove(Object key) { SimpleCache.CacheObject<V> cacheObject = map.get(key); if (cacheObject == null) { return null; } map.remove(key); cacheObject.accessedNode.remove(); cacheObject.accessedNode = null; return cacheObject.value; } /* * 清空整个cache */ public synchronized void clear() { Object[] keys = map.keySet().toArray(); for (int i = 0; i < keys.length; i++) { remove(keys[i]); } map.clear(); accessedList.clear(); accessedList = new List(); } /* * 是否包含key */ public boolean containsKey(Object key) { return map.containsKey(key); } /* * 当前cache的key set */ public Set<K> keySet() { synchronized (this) { return new HashSet<K>(map.keySet()); } } /* * 当前cache的entry Set * 代价较大 */ public Set<Map.Entry<K, V>> entrySet() { synchronized (this) { final Map<K, V> result = new HashMap<K, V>(); for (final Map.Entry<K, SimpleCache.CacheObject<V>> entry : map.entrySet()) { result.put(entry.getKey(), entry.getValue().value); } return result.entrySet(); } } /* * 当前cache的value集合 * 代价较大 */ public Object[] values() { Object[] array = new Object[size()]; if(!accessedList.isEmpty()) { int i = 0; ListNode node = accessedList.getLast(); while(node != accessedList.getFirst().previous) { array[i++] = map.get(node.object).value; node = node.previous; } } return array; } /* * 裁剪cache使之大小最大为maxSiza */ private void cull(){ while(map.size() > maxSize){ remove(accessedList.getLast().object); } } /** * cache对象,封装了value对象 * 内部保存了一个链表节点的引用,便于快速找到对应的链表节点 */ private static class CacheObject<V> { public V value; public ListNode accessedNode; /* * 构造函数 */ public CacheObject(V value) { this.value = value; }// }//CacheObject<V> } 这个cache的简单使用: package SimpleCache; import java.math.BigDecimal; import SimpleCache.SimpleCache; import RoomPerson.Person; import RoomPerson.Room; public class testSimpleCache { public static void main(String[] args){ int Size = 3; //空间大小 SimpleCache<Room, Person> cache = new SimpleCache<Room, Person>(Size); Room room1 = new Room(new String("room1"), 10, new BigDecimal(100), new String("address1"), new String("1111111")); Room room2 = new Room(new String("room2"), 20, new BigDecimal(200), new String("address2"), new String("2222222")); Room room3 = new Room(new String("room3"), 30, new BigDecimal(300), new String("address3"), new String("3333333")); Room room4 = new Room(new String("room4"), 30, new BigDecimal(300), new String("address4"), new String("4444444")); Person person1 = new Person(new String("person1"), 20, 60); Person person2 = new Person(new String("person2"), 25, 65); Person person3 = new Person(new String("person3"), 30, 70); Person person4 = new Person(new String("person4"), 35, 75); cache.put(room1, person1); //(room1, person1)在首端, (room1, person1)在尾端 cache.put(room2, person2); //(room1, person1)在首端, (room2, person2)在尾端 cache.put(room3, person3); //(room1, person1)在首端, (room3, person3)在尾端 cache.get(room1); //(room2, person2)在首端, (room1, person1)在尾端 cache.put(room4, person4); //(room2, person2)被删除,(room3, person3)在首端, (room4, person4)在尾端 Object[] values = cache.values(); for (int i = 0; i < values.length; i++)//LRU策略,结果应该依次:person3, person1 , person4 { System.out.println(values[i]); } } }