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;}
}

原文地址:https://www.cnblogs.com/zhy-study/p/9498560.html

时间: 2024-11-08 05:28:58

LRU 实现缓存的相关文章

【面试题】LRU算法及编码实现LRU策略缓存

概念 LRU(least recently used)就是将最近不被访问的数据给淘汰掉,LRU基于一种假设:认为最近使用过的数据将来被使用的概率也大,最近没有被访问的数据将来被使用的概率比较低. 原理 LRU一般通过链表形式来存放缓存数据,新插入或被访问的数据放在链表头部,超过一定阈值后,自动淘汰链表尾部的数据.下图很形象的说明了LRU缓存淘汰过程.(图片来自网络) 步骤: 1.新插入A, 将A放置在队列头部 2.新插入B, 将B放置在队列头部, A自动推举次席. 3.新插入C, 将C放置在队列

10行Java代码实现最近被使用(LRU)缓存

在最近的面试中,我曾被多次问到,怎么实现一个最近最少使用(LRU)的缓存.缓存可以通过哈希表来实现,然而为这个缓存增加大小限制会变成另一个有意思的问题.现在我们看一下怎么实现. 最近最少使用缓存的回收 为了实现缓存回收,我们需要很容易做到: 查询出最近最晚使用的项 给最近使用的项做一个标记 链表可以实现这两个操作.检测最近最少使用的项只需要返回链表的尾部.标记一项为最近使用的项只需要从当前位置移除,然后将该项放置到头部.比较困难的事情是怎么快速的在链表中找到该项. 哈希表的帮助 看一下我们工具箱

【leetcode】:LRU Cache_缓存淘汰算法LRU的设计与实现

内存淘汰算法是一个比较重要的算法,经常会被问道:如果让你设计一个LRU算法你会怎么做?尽可能的保持存取的高效.那么就依着这道算法题对LRU进行一个简单的介绍. 题目地址:https://oj.leetcode.com/problems/lru-cache/ 1.什么是LRU算法?为什么使用LRU? LRU即Least Recently Used的缩写,即最近最少使用的意思.我们知道在内存空间是有限的,那么当内存被数据占满的时候,而需要访问的数据又不在内存中,那么就需要将内存中的最少使用的数据淘汰

浅析LRU(K-V)缓存

LRU(Least Recently Used)算法是缓存技术中的一种常见思想,顾名思义,最近最少使用,也就是说有两个维度来衡量,一个是时间(最近),一个频率(最少).如果需要按优先级来对缓存中的K-V实体进行排序的话,需要考虑这两个维度,在LRU中,最近使用频率最高的排在前面,也可以简单的说最近访问的排在前面.这就是LRU的大体思想. 在操作系统中,LRU是用来进行内存管理的页面置换算法,对于在内存中但又不用的数据块(内存块)叫做LRU,操作系统会根据哪些数据属于LRU而将其移出内存而腾出空间

[LeetCode] LRU Cache 缓存器

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set. get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1. set

[LintCode] LRU Cache 缓存器

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set. get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.set(

缓存淘汰算法--LRU算法

1. LRU1.1. 原理 LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是"如果数据最近被访问过,那么将来被访问的几率也更高". 1.2. 实现 最常见的实现是使用一个链表保存缓存数据,详细算法实现如下: 1. 新数据插入到链表头部: 2. 每当缓存命中(即缓存数据被访问),则将数据移到链表头部: 3. 当链表满的时候,将链表尾部的数据丢弃. 1.3. 分析 [命中率] 当存在热点数据时,LRU的效率很好,但偶发性的

缓存算法–LRU

LRU LRU是Least Recently Used 的缩写,翻译过来就是“最近最少使用”,也就是说,LRU缓存把最近最少使用的数据移除,让给最新读取的数据.而往往最常读取的,也是读取次数最多的,所以,利用LRU缓存,我们能够提高系统的performance. LRU实现 1. 新数据插入到链表头部: 2. 每当缓存命中(即缓存数据被访问),则将数据移到链表头部: 3. 当链表满的时候,将链表尾部的数据丢弃. LRU分析 [命中率] 当存在热点数据时,LRU的效率很好,但偶发性的.周期性的批量

LRU缓存策略

描述: 为最近最少使用(LRU)缓存策略设计一个数据结构,它应该支持以下操作:获取数据(get)和写入数据(set). 获取数据get(key):如果缓存中存在key,则获取其数据值(通常是正数),否则返回-1. 写入数据set(key, value):如果key还没有在缓存中,则写入其数据值.当缓存达到上限,它应该在写入新数据之前删除最近最少使用的数据用来腾出空闲位置. 第一次提交:编译警告 Solution.java:36: error: cannot find symbolreturn m