LRU算法,也叫最近最少使用算法,我们可以使用该算法来实现cache机制,简单地说就是缓存一定量的数据,当超过设定阀值的时候就把一些过期的数据删除掉,本篇文章我们来看看如何实现LRU Cache,下面我们使用两种方式来实现。
基于LinkedHashMap
在java的集合类中有LinkedHashMap类,当参数accessOrder为true的时候,就会按照访问顺序排序,最后访问的放在最前面,最早访问的放在后面,这样我们就可以实现LRU算法了。这种方式比较简单,代码如下:
public class LRU {
private final int CAPACITY=0;
private LinkedHashMap<Integer,Integer> cache;
public LRU(int capacity){
cache=new LinkedHashMap<Integer,Integer>(capacity,0.75f,true){
@Override
protected boolean removeEldestEntry(java.util.Map.Entry<Integer, Integer> eldest) {
return size()>CAPACITY;
}
};
}
public int get(int key) {
return cache.getOrDefault(key, -1);
}
public void put(int key, int value) {
cache.put(key, value);
}
}
链表+HashMap
第二种方式是使用链表+HashMap的方式来实现,需要我们自己实现一系列方法,代码如下:
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
/**
* LRUCache链表+hashmap的实现方式
* @author shinelon
*
*/
public class LRUCache2<K,V>{
public final int CACHE_SIZE;
public Entry frist;
public Entry last;
public HashMap<K,Entry<K,V>> hashMap;
public LRUCache2(int cacheSize){
this.CACHE_SIZE=cacheSize;
hashMap=new HashMap<K,Entry<K,V>>();
}
public void put(K key,V value){
Entry entry=getEntry(key);
if(entry==null){
if(hashMap.size()>=CACHE_SIZE){
hashMap.remove(last.key);
removeLast();
}
entry=new Entry();
entry.key=key;
}
entry.value=value;
moveToFrist(entry);
hashMap.put(key, entry);
}
public V get(K key){
Entry<K,V> entry=getEntry(key);
if(entry==null)
return null;
moveToFrist(entry);
return entry.value;
}
private void moveToFrist(Entry entry) {
if(entry==frist)
return;
if(entry.pre!=null)
entry.pre.next=entry.next;
if(entry.next!=null)
entry.next.pre=entry.pre;
if(last==entry)
last=last.pre;
if(frist==null||last==null){
frist=last=entry;
return;
}
entry.next=frist;
frist.pre=entry;
frist=entry;
frist.pre=null;
}
private void removeLast() {
if(last!=null){
last=last.pre;
if(last==null)
frist=null;
else
last.next=null;
}
}
public Entry getEntry(K key){
return hashMap.get(key);
}
public void print(HashMap<K,Entry<K,V>> map){
Collection<Entry<K,V>> entry=map.values();
Iterator it=entry.iterator();
while(it.hasNext()){
Entry<K,V> e=(LRUCache2<K, V>.Entry<K, V>) it.next();
System.out.println(e.key+" : "+e.value);
}
}
class Entry<K,V>{
Entry pre;
Entry next;
K key;
V value;
}
public static void main(String[] args) {
LRUCache2<String, String> cache=new LRUCache2<>(3);
cache.put("one", "1");
cache.put("tow", "2");
cache.put("three", "3");
System.out.println("first entry: "+cache.frist.key);
cache.print(cache.hashMap);
cache.put("four", "4");
System.out.println("============================");
System.out.println("first entry: "+cache.frist.key);
cache.print(cache.hashMap);
cache.put("five", "5");
System.out.println("============================");
System.out.println("first entry: "+cache.frist.key);
cache.print(cache.hashMap);
}
}