LRU算法学习



http://blog.youkuaiyun.com/beiyeqingteng/article/details/7010411

第一种是使用LinkedHashMap红黑树实现

package lru;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

public class LRUCache<K, V> {
 private static final float hashTableLoadFactor = 0.75f;

 private LinkedHashMap<K, V> map;
 private int cacheSize;

 /**
  * Creates a new LRU cache.
  *
  * @param cacheSize
  *            the maximum number of entries that will be kept in this cache.
  */
 public LRUCache(int cacheSize) {
  this.cacheSize = cacheSize;
  int hashTableCapacity = (int) Math.ceil(cacheSize / hashTableLoadFactor) + 1;
  map = new LinkedHashMap<K, V>(hashTableCapacity, hashTableLoadFactor,true) {
   // (an anonymous inner class)
   private static final long serialVersionUID = 1;

   @Override
   protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
    return size() > LRUCache.this.cacheSize;
   }
   
  };
 }

 /**
  * Retrieves an entry from the cache.<br>
  * The retrieved entry becomes the MRU (most recently used) entry.
  *
  * @param key
  *            the key whose associated value is to be returned.
  * @return the value associated to this key, or null if no value with this
  *         key exists in the cache.
  */
 public synchronized V get(K key) {
  return map.get(key);
 }

 /**
  * Adds an entry to this cache. The new entry becomes the MRU (most recently
  * used) entry. If an entry with the specified key already exists in the
  * cache, it is replaced by the new entry. If the cache is full, the LRU
  * (least recently used) entry is removed from the cache.
  *
  * @param key
  *            the key with which the specified value is to be associated.
  * @param value
  *            a value to be associated with the specified key.
  */
 public synchronized void put(K key, V value) {
  map.put(key, value);
 }

 /**
  * Clears the cache.
  */
 public synchronized void clear() {
  map.clear();
 }

 /**
  * Returns the number of used entries in the cache.
  *
  * @return the number of entries currently in the cache.
  */
 public synchronized int usedEntries() {
  return map.size();
 }

 /**
  * Returns a <code>Collection</code> that contains a copy of all cache
  * entries.
  *
  * @return a <code>Collection</code> with a copy of the cache content.
  */
 public synchronized Collection<Map.Entry<K, V>> getAll() {
  return new ArrayList<Map.Entry<K, V>>(map.entrySet());
 }

}

public class Run {
 // Test routine for the LRUCache class.
 public static void main(String[] args) {
  LRUCache<String, String> c = new LRUCache<String, String>(3);
  c.put("1", "one"); // 1
  c.put("2", "two"); // 2 1
  c.put("3", "three"); // 3 2 1
  c.put("4", "four"); // 4 3 2
  if (c.get("2") == null){
   throw new Error(); // 2 4 3
  }
  c.put("5", "five"); // 5 2 4
  c.put("4", "second four"); // 4 5 2
  // Verify cache content.
  if (c.usedEntries() != 3){
   throw new Error();
  }
  if (!c.get("4").equals("second four")) {
   throw new Error();
  }
  if (!c.get("5").equals("five")){
   throw new Error();
  }
  if (!c.get("2").equals("two")){
   throw new Error();
  }
  // List cache content.
  for (Map.Entry<String, String> e : c.getAll())
   System.out.println(e.getKey() + " : " + e.getValue());
 }
}

第二种使用链表和hashTable实现:

package lru;

import java.util.Hashtable;

public class HashTableLRUCache {
 private int cacheSize;
 private Hashtable<Object, Entry> nodes;// 缓存容器
 private int currentSize;
 private Entry first;// 链表头
 private Entry last;// 链表尾

 public HashTableLRUCache(int i) {
  currentSize = 0;
  cacheSize = i;
  nodes = new Hashtable<Object, Entry>(i);// 缓存容器
 }

 /**
  * 获取缓存中对象,并把它放在最前面
  */
 public Entry get(Object key) {
  Entry node = nodes.get(key);
  if (node != null) {
   moveToHead(node);
   return node;
  } else {
   return null;
  }
 }

 /**
  * 添加 entry到hashtable, 并把entry
  */
 public void put(Object key, Object value) {
  // 先查看hashtable是否存在该entry, 如果存在,则只更新其value
  Entry node = nodes.get(key);

  if (node == null) {
   // 缓存容器是否已经超过大小.
   if (currentSize >= cacheSize) {
    nodes.remove(last.key);
    removeLast();
   } else {
    currentSize++;
   }
   node = new Entry();
  }
  node.value = value;
  // 将最新使用的节点放到链表头,表示最新使用的.
  moveToHead(node);
  nodes.put(key, node);
 }

 /**
  * 将entry删除, 注意:删除操作只有在cache满了才会被执行
  */
 public void remove(Object key) {
  Entry node = nodes.get(key);
  // 在链表中删除
  if (node != null) {
   if (node.prev != null) {
    node.prev.next = node.next;
   }
   if (node.next != null) {
    node.next.prev = node.prev;
   }
   if (last == node)
    last = node.prev;
   if (first == node)
    first = node.next;
  }
  // 在hashtable中删除
  nodes.remove(key);
 }

 /**
  * 删除链表尾部节点,即使用最后 使用的entry
  */
 private void removeLast() {
  // 链表尾不为空,则将链表尾指向null. 删除连表尾(删除最少使用的缓存对象)
  if (last != null) {
   if (last.prev != null) {
    last.prev.next = null;
   } else {
    first = null;
   }
   last = last.prev;
  }
 }

 /**
  * 移动到链表头,表示这个节点是最新使用过的
  */
 private void moveToHead(Entry node) {
  if (node == first) {
   return;
  }
  if (node.prev != null) {
   node.prev.next = node.next;
  }
  if (node.next != null) {
   node.next.prev = node.prev;
  }
  if (last == node) {
   last = node.prev;
  }
  if (first != null) {
   node.next = first;
   first.prev = node;
  }
  first = node;
  node.prev = null;
  if (last == null) {
   last = first;
  }
 }

 /*
  * 清空缓存
  */
 public void clear() {
  first = null;
  last = null;
  currentSize = 0;
 }

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值