简介

LRU即(Least Recent Used)最近最少使用。缓存可以用HashMap去模拟,用String作为key去访问数据,当缓存满了的时候,我们就需要将最近最少使用的删掉。如果额外开辟空间去标记最近使用就很麻烦了,我们可以用双向链表去进行模拟。

当缓存新增节点时:该节点放到链表最前面。
当缓存数据被访问时:节点放到最前面
当缓存满时:将最后面的节点删除

基于HashMap

  • 代码如下:

    public class LRUNode {
      String key;
      Object value;
      LRUNode prev;
      LRUNode next;
    
      public LRUNode(String key, Object value) {
          this.key = key;
          this.value = value;
      }
    }
    public class LRUCache {
    
      private HashMap<String,LRUNode> map;
      private int capcity;
      private LRUNode head;
      private LRUNode tail;
    
      public LRUCache(int capcity) {
          this.capcity = capcity;
      }
    
      public Object get(String key){
          LRUNode node = map.get(key);
          if (node != null){
              remove(node,false);
              setHead(node);
              return node.value;
          }
          return null;
      }
    
      public void set(String key,Object value){
          LRUNode node = map.get(key);
    
          if (node != null){
              node.value = value;
              remove(node,false);
              setHead(node);
          }else {
              node = new LRUNode(key, value);
              if (map.size() >= capcity){
                  remove(tail,true);
              }
              map.put(key, node);
              setHead(node);
          }
      }
      private void setHead(LRUNode node) {
          if (head != null) {
              node.next = head;
              head.prev = node;
          }
          head = node;
          if (tail == null) {
              {
                  tail = node;
              }
          }
      }
      private void remove(LRUNode node,boolean flag){
          if (node.prev != null){
              node.prev.next = null;
          }else {
              head = node.next;
          }
    
          if (node.next != null){
              node.next.prev = node.prev;
          }else {
              tail = node.prev;
          }
    
          node.next = null;
          node.prev = null;
    
          if (flag){
              map.remove(node,flag);
          }
      }
    }

基于LinkedHashMap实现

public class LRUCache<K,V> extends LinkedHashMap<K,V> {

    private final int CACHE_SIZE;

    public LRUCache(int cacheSize){
        // true基于访问排序,false基于插入排序
        super((int) (Math.ceil(cacheSize / 0.75) + 1),0.75f,true);
        CACHE_SIZE = cacheSize;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        // 当 map中的数据量大于指定的缓存个数的时候,就自动删除最老的数据。
        return size() > CACHE_SIZE;
    }
}