【算法系列】淘汰算法之LRU

LRU算法

LRU(The Least Recently Used)最近最少使用。

LRU算法的思想

如果一个数据在最近一段时间没有被访问到,那么可以认为在将来它被访问的可能性也很小。

因此,当空间满时,最久未被使用的数据最先被淘汰。

LRU算法的描述

设计一种缓存结构,该结构在构造时确定大小,假设大小为 K,并有两个功能:

  • put(key, value)将记录(key, value)插入该结构。当缓存满时,将最久未使用的数据淘汰掉。

  • get(key)返回key对应的value值。

LRU算法的实现

  1. 最朴素的思想就是用数组+时间戳的方式,不过这样做效率较低。

  2. 我们可以用双向链表(LinkedList)+哈希表(HashMap)实现(链表用来表示位置,哈希表用来存储和查找)。

  3. 直接使用Java里有的数据结构LinkedHashMap

LRUCache

package com.itplh;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author: tanpenggood
 * @date: 2020-09-17 10:49
 */
public class LRUCache<K, V> extends LinkedHashMap<K, V> {
    
    
    private int cacheSize;

    public LRUCache(int cacheSize) {
    
    
    	// LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder)
        // 关键:使用的三个参数的构造方法,将accessOrder设置为true,LinkedHashMap默认为false
        super(16, (float) 0.75, true);
        this.cacheSize = cacheSize;
    }

	/**
     * 当缓存空间不够时,淘汰最久未使用的数据
     * 
     */
    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
    
    
        return size() > cacheSize;
    }

}

LRUCacheTest

package com.itplh;

import lombok.extern.slf4j.Slf4j;

/**
 * @author: tanpenggood
 * @date: 2020-09-17 10:49
 */
@Slf4j
public class LRUCacheTest {
    
    

    public static void main(String[] args) {
    
    
        LRUCache<String, Integer> cache = new LRUCache<>(5);
        for (int i = 1; i <= 5; i++) {
    
    
            cache.put("k" + i, i);
        }
        log.info("all cache: {}", cache);
        cache.get("k3");
        log.info("get k3: {}", cache);
        cache.get("k4");
        log.info("get k4: {}", cache);
        cache.get("k4");
        log.info("get k4: {}", cache);
        cache.put("k" + 10, 10);
        log.info("After running the LRU algorithm cache: {}", cache);
    }
}

Output

all cache: {
    
    k1=1, k2=2, k3=3, k4=4, k5=5}
get k3: {
    
    k1=1, k2=2, k4=4, k5=5, k3=3}
get k4: {
    
    k1=1, k2=2, k5=5, k3=3, k4=4}
get k4: {
    
    k1=1, k2=2, k5=5, k3=3, k4=4}
After running the LRU algorithm cache: {
    
    k2=2, k5=5, k3=3, k4=4, k10=10}

总结

  1. 每一次从cacheget数据时会将取出来的元素移到队尾。
  2. cacheput数据时,先将新数据存到队尾,再判断缓存空间是否够用,若空间不够,则淘汰队首(最久未使用)的元素。

参考

缓存算法(FIFO 、LRU、LFU三种算法的区别)

猜你喜欢

转载自blog.csdn.net/AV_woaijava/article/details/108638788