LRU缓存机制的实现

Posted

tags:

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

参考技术A leetcode 146.

LRU(Least Recently Used)是一种缓存替换策略。现实生活中,缓存的大小总是有限的,为了合理地利用缓存,在缓存满了以后需要利用合适的替换策略把某些内容从缓存中移出,以腾出空间给新的元素。LRU就是其中一种常见的策略,它把缓存中最不常访问到的数据移出。
为了实现LRU,可以利用哈希表+双向链表。哈希表以键值对的形式保存元素,并以O(1)的时间复杂度取出元素;双向链表用于记录每个元素的使用情况。具体如下:

参考:
[1] https://zhuanlan.zhihu.com/p/76553221

java 自定义 LRU(最近最少使用)策略 实现 缓存机制

1. java提供了一个简单的方式实现LRU:  LinkedHashMap

 

 2. 自定义实现

LRU至少需要两个主要操作: 添加(add)和搜索(search)

public class LRUCache {
    private Map<String, CacheEntry> map;
    private CacheEntry head , tail;
    private int maxSize;
    public LRUCache(int maxSize){
        if(maxSize < 1){
            throw new IllegalArgumentException("Cache maxSize has to be at least 1");
        }
        this.map = new HashMap<String, CacheEntry>();
        head = new CacheEntry("head","");
        tail = new CacheEntry("tail", "");
        head.setNext(tail);
        tail.setPrev(head);
        this.maxSize = maxSize;
    }
    public void add(String key, String value){
        CacheEntry cacheEntry = map.get(key);
        if(cacheEntry == null){
            cacheEntry = new CacheEntry(key, value);
            if(map.size() == maxSize){
                //缓存达到最大数目
                //删除最老的条目
                CacheEntry deleteEntry = tail.getPrev();
                //从map中移除
                map.remove(deleteEntry.getKey());
                //从队列中移除
                remove(deleteEntry);
            }
            //添加条目到队列
            addFront(cacheEntry);
            //添加到map
            map.put(key, cacheEntry);
        }else{
            //更新值
            cacheEntry.setValue(value);
            //访问条目
            accessed(cacheEntry);
        }
    }

    public String search(String key){
        CacheEntry entry = map.get(key);
        if(entry == null){
            return null;
        }
        accessed(entry);
        return entry.getValue();
    }
    //打印缓存内容
    public void print(){
        CacheEntry entry = head.getNext();
        while(entry != tail){
            System.out.println("{" + entry.getKey() + ":" + entry.getValue() + "}");
            entry = entry.getNext();
        }
        System.out.println();
    }

    public void accessed(CacheEntry entry) {
        if(entry.getPrev() != head){
            remove(entry);
            addFront(entry);
        }
    }

    private void addFront(CacheEntry entry) {
        //在队列的头部添加条目
        CacheEntry nextEntry = head.getNext();
        head.setNext(entry);
        entry.setPrev(head);
        entry.setNext(nextEntry);
        if(nextEntry != null){
            nextEntry.setPrev(entry);
        }
    }

    private void remove(CacheEntry entry) {
        if(entry == head || entry == tail){
            return;//错误
        }
        entry.getPrev().setNext(entry.getNext());
        if(entry.getNext() != null){
            entry.getNext().setPrev(entry.getPrev());
        }
    }
}
/**
 * Created by admin on 2018/3/30.
 */
public class CacheEntry {
    private CacheEntry prev, next;
    private String key, value;
    CacheEntry(String key, String value){
        this.key = key;
        this.value = value;
    }

    public CacheEntry getPrev() {
        return prev;
    }

    public void setPrev(CacheEntry prev) {
        this.prev = prev;
    }

    public CacheEntry getNext() {
        return next;
    }

    public void setNext(CacheEntry next) {
        this.next = next;
    }

    public String getKey() {
        return key;
    }


    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

 

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

LRU 缓存机制及 3 种简单实现

leetcode146. LRU缓存机制

算法:LRU缓存机制

LeetCode 146. LRU 缓存机制

Leetcode No.146 LRU 缓存机制

LeetCode #146 LRU缓存机制