LRU 实现缓存

Posted zhy-study

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LRU 实现缓存相关的知识,希望对你有一定的参考价值。

LRU:Least Recently used 最近最少使用

 

1.使用LinkedHashMap实现 inheritance实现方式 继承map类 可以使用Collections.synchronizedMap方式实现线程安全的操作

public class LruCache<K,V> extends LinkedHashMap<K,V> {
    private final int MAX_CACHE_SIZE;
    public LruCache(int cacheSize) {
        super((int)Math.ceil(cacheSize/0.75)+1,0.75f,true );
        MAX_CACHE_SIZE = cacheSize;
    }
    @Override
    protected boolean removeEldestEntry(Map.Entry eldest){
        return size()> MAX_CACHE_SIZE;
    }

    @Override
    public String toString(){
        StringBuilder sb= new StringBuilder();
        for(Map.Entry<K,V> entry : entrySet()){
            sb.append(String.format("%s:%s",entry.getKey(),entry.getValue()));
        }
        return sb.toString();
    }
}

2、LinkedHashMap 使用delegation方式实现

没有map接口 

public class LruByDelegation<K,V> {

    private final int MAX_CACHE_SIZE;
    private final float DEFAULT_LOAD_FACTOR = 0.75f;
    LinkedHashMap<K,V> map;

    public LruByDelegation(int cacheSize) {
        this.MAX_CACHE_SIZE = cacheSize;

        int capacity = (int) (Math.ceil(MAX_CACHE_SIZE/DEFAULT_LOAD_FACTOR)+1);
        map= new LinkedHashMap(capacity,DEFAULT_LOAD_FACTOR,true){
            @Override
            protected boolean removeEldestEntry(Map.Entry eldest){
                return size()>MAX_CACHE_SIZE;
            }
        };
    }

    public synchronized void put(K key,V value){
        map.put(key,value);
    }

    public synchronized V get(K key){
        return map.get(key);
    }
    public synchronized void remove(K key){
        map.remove(key);
    }
    public synchronized Set<Map.Entry<K,V>> getAll(){
        return map.entrySet();
    }
    public synchronized int size(){
        return map.size();
    }
    public synchronized void clear(){
        map.clear();
    }

    @Override
    public String toString(){
        StringBuilder sb= new StringBuilder();
        for(Map.Entry entry : map.entrySet()){
            sb.append(String.format("%s:%s",entry.getKey(),entry.getValue()));
        }
        return sb.toString();
    }

}

2 Cache链表+HashMap实现   Entry自己定义  总结一下就是各种pre 和 next指针的变换

public class LruCache01<K,V> {
    private final int MAX_CACHE_SIZE;
    private Entry first;
    private Entry last;
    private HashMap<K, Entry<K,V>> hashMap;

    public LruCache01(int MAX_CACHE_SIZE) {
        this.MAX_CACHE_SIZE = MAX_CACHE_SIZE;
        hashMap=new HashMap<>();
    }
    public void put(K key, V value){
        Entry entry = getEntry(key);
        if(entry==null){
            if(hashMap.size()>=MAX_CACHE_SIZE){
                hashMap.remove(last.key);
                //removeLast
                removeLast();
            }
            entry=new Entry();
            entry.key=key;
        }
        entry.value=value;
        moveToFirst(entry);
        hashMap.put(key,entry);

    }
    public V get(K  key){
        Entry entry  = getEntry(key);
        if(entry==null)
            return null;
        moveToFirst(entry);
        return (V) entry.value;
    }

    public void remove(K key){
        Entry entry = getEntry(key);
        if(entry!=null){
            if(entry.pre!=null)
                entry.pre.next=entry.next;
            if(entry.next!=null)
                entry.next.pre=entry.pre;
            if(entry==first)
                first=entry.next;
            if(entry==last)
                last=entry.pre;
        }
        hashMap.remove(key);
    }
    public void moveToFirst(Entry entry){
        if(entry==first)
            return;
        if(entry.pre!=null)
            entry.pre.next=entry.next;
        if(entry.next!=null)
            entry.next.pre=entry.pre;
        if(entry==last)
            last=last.pre;
        if(first==null || last==null){
            first=last=entry;
            return;
        }
        entry.next=first;
        first.pre=entry;
        first=entry;
        entry.pre=null;
    }


    public void removeLast(){
        if(last!=null){
            last=last.pre;
            if(last==null)
                first=null;
            else
                last.next=null;
        }
    }

    public Entry<K,V> getEntry(K key){
        return hashMap.get(key);
    }

    @Override
    public String toString(){
        StringBuilder sb= new StringBuilder();
        Entry entry = first;
        while(entry!=null){
            sb.append(String.format("%s:%s",entry.key,entry.value));
            entry=entry.next;
        }
        return sb.toString();
    }
}
class Entry<K,V>{
    public Entry pre;
    public Entry next;
    public K key;
    public V value;
}

LinkedHashMap的FIFO实现

只需要重新removeEldestEntry方法可以实现FIFO缓存

final int cacheSize=5;
LinkedHashMap<Integer,String> lru = new LinkedHashMap<Integer,String>(){
  @Override
protected boolean removeEldestEntry(Map.Entry<Integer,String> eldest){
return size()>cacheSize;}  
}

 

以上是关于LRU 实现缓存的主要内容,如果未能解决你的问题,请参考以下文章

LRU算法实现

LeetCode第146题—LRU缓存机制—Python实现

Java 实现 LRU 缓存算法

LeetCode 146. LRU 缓存

LRU算法的实现

带你学会 LRU 算法相关内容