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]);
    }
 }
}

 

posted @ 2013-05-21 15:27  坏混混  阅读(400)  评论(0编辑  收藏  举报