【算法】―― LRU算法

匿名 (未验证) 提交于 2019-12-03 00:39:02

LRU原理

LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。

实现1












命中时需要遍历链表,找到命中的数据块索引,然后需要将数据移到头部。

import java.util.ArrayList;   import java.util.Collection;   import java.util.LinkedHashMap;   import java.util.concurrent.locks.Lock;   import java.util.concurrent.locks.ReentrantLock;   import java.util.Map;     /**   * 类说明:利用LinkedHashMap实现简单的缓存, 必须实现removeEldestEntry方法,具体参见JDK文档   *    * @author dennis   *    * @param <K>   * @param <V>   */  public class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V> {       private final int maxCapacity;        private static final float DEFAULT_LOAD_FACTOR = 0.75f;        private final Lock lock = new ReentrantLock();        public LRULinkedHashMap(int maxCapacity) {           super(maxCapacity, DEFAULT_LOAD_FACTOR, true);           this.maxCapacity = maxCapacity;       }        @Override      protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {           return size() > maxCapacity;       }       @Override      public boolean containsKey(Object key) {           try {               lock.lock();               return super.containsKey(key);           } finally {               lock.unlock();           }       }         @Override      public V get(Object key) {           try {               lock.lock();               return super.get(key);           } finally {               lock.unlock();           }       }        @Override      public V put(K key, V value) {           try {               lock.lock();               return super.put(key, value);           } finally {               lock.unlock();           }       }        public int size() {           try {               lock.lock();               return super.size();           } finally {               lock.unlock();           }       }        public void clear() {           try {               lock.lock();               super.clear();           } finally {               lock.unlock();           }       }        public Collection<Map.Entry<K, V>> getAll() {           try {               lock.lock();               return new ArrayList<Map.Entry<K, V>>(super.entrySet());           } finally {               lock.unlock();           }       }   }  

实现2


传统意义的LRU算法是为每一个Cache对象设置一个计数器,每次Cache命中则给计数器+1,而Cache用完,需要淘汰旧内容,放置新内容时,就查看所有的计数器,并将最少使用的内容替换掉。






非线程安全,若实现安全,则在响应的方法加锁。

import java.util.HashMap; import java.util.Map.Entry; import java.util.Set;   public class LRUCache<K, V> {      private int currentCacheSize;     private int CacheCapcity;     private HashMap<K,CacheNode> caches;     private CacheNode first;     private CacheNode last;      public LRUCache(int size){         currentCacheSize = 0;         this.CacheCapcity = size;         caches = new HashMap<K,CacheNode>(size);     }      public void put(K k,V v){         CacheNode node = caches.get(k);         if(node == null){             if(caches.size() >= CacheCapcity){                  caches.remove(last.key);                 removeLast();             }             node = new CacheNode();             node.key = k;         }         node.value = v;         moveToFirst(node);         caches.put(k, node);     }      public Object  get(K k){         CacheNode node = caches.get(k);         if(node == null){             return null;         }         moveToFirst(node);         return node.value;     }      public Object remove(K k){         CacheNode node = caches.get(k);         if(node != null){             if(node.pre != null){                 node.pre.next=node.next;             }             if(node.next != null){                 node.next.pre=node.pre;             }             if(node == first){                 first = node.next;             }             if(node == last){                 last = node.pre;             }         }          return caches.remove(k);     }      public void clear(){         first = null;         last = null;         caches.clear();     }        private void moveToFirst(CacheNode node){         if(first == node){             return;         }         if(node.next != null){             node.next.pre = node.pre;         }         if(node.pre != null){             node.pre.next = node.next;         }         if(node == last){             last= last.pre;         }         if(first == null || last == null){             first = last = node;             return;         }          node.next=first;         first.pre = node;         first = node;         first.pre=null;      }      private void removeLast(){         if(last != null){             last = last.pre;             if(last == null){                 first = null;             }else{                 last.next = null;             }         }     }     @Override     public String toString(){         StringBuilder sb = new StringBuilder();         CacheNode node = first;         while(node != null){             sb.append(String.format("%s:%s ", node.key,node.value));             node = node.next;         }          return sb.toString();     }      class CacheNode{         CacheNode pre;         CacheNode next;         Object key;         Object value;         public CacheNode(){          }     }      public static void main(String[] args) {          LRUCache<Integer,String> lru = new LRUCache<Integer,String>(3);          lru.put(1, "a");    // 1:a         System.out.println(lru.toString());         lru.put(2, "b");    // 2:b 1:a          System.out.println(lru.toString());         lru.put(3, "c");    // 3:c 2:b 1:a          System.out.println(lru.toString());         lru.put(4, "d");    // 4:d 3:c 2:b           System.out.println(lru.toString());         lru.put(1, "aa");   // 1:aa 4:d 3:c           System.out.println(lru.toString());         lru.put(2, "bb");   // 2:bb 1:aa 4:d         System.out.println(lru.toString());         lru.put(5, "e");    // 5:e 2:bb 1:aa         System.out.println(lru.toString());         lru.get(1);         // 1:aa 5:e 2:bb         System.out.println(lru.toString());         lru.remove(11);     // 1:aa 5:e 2:bb         System.out.println(lru.toString());         lru.remove(1);      //5:e 2:bb         System.out.println(lru.toString());         lru.put(1, "aaa");  //1:aaa 5:e 2:bb         System.out.println(lru.toString());     }  }

原文:https://www.cnblogs.com/bopo/p/9255654.html

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!