Guava---缓存之LRU算法

简介

LRU全称是Least Recently Used,即最近最久未使用的意思。

LRU算法的设计原则是:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。

实现LRU

1.用一个数组来存储数据,给每一个数据项标记一个访问时间戳,每次插入新数据项的时候,先把数组中存在的数据项的时间戳自增,并将新数据项的时间戳置为0并插入到数组中。每次访问数组中的数据项的时候,将被访问的数据项的时间戳置为0。当数组空间已满时,将时间戳最大的数据项淘汰。

2.利用一个链表来实现,每次新插入数据的时候将新数据插到链表的头部;每次缓存命中(即数据被访问),则将数据移到链表头部;那么当链表满的时候,就将链表尾部的数据丢弃。

3.利用链表和hashmap。当需要插入新的数据项的时候,如果新数据项在链表中存在(一般称为命中),则把该节点移到链表头部,如果不存在,则新建一个节点,放到链表头部,若缓存满了,则把链表最后一个节点删除即可。在访问数据的时候,如果数据项在链表中存在,则把该节点移到链表头部,否则返回-1。这样一来在链表尾部的节点就是最近最久未访问的数据项。

对于第一种方法,需要不停地维护数据项的访问时间戳,另外,在插入数据、删除数据以及访问数据时,时间复杂度都是O(n)。对于第二种方法,链表在定位数据的时候时间复杂度为O(n)。所以在一般使用第三种方式来是实现LRU算法。

LinkedHashMap中LRU算法实现

/**
 * @Author: Kingcym
 * @Description:  非线程安全
 * @Date: 2018/11/11 19:09
 */
public class LinkedHashLRUcache<k, v> {
    /**
     * LinkedHashMap(自身实现了LRU算法)
     * 1.有序
     * 2.每次访问一个元素,都会提到最后面去
     */
    private static class InternalLRUcache<k, v> extends LinkedHashMap<k, v> {
        private final int limit;

        private InternalLRUcache(int limit) {
            super(16, 0.75f, true);
            this.limit = limit;
        }

        //是否删除最老的数据
        @Override
        protected boolean removeEldestEntry(Map.Entry<k, v> eldest) {
            return size() > limit;
        }
    }

    private final int limit;
    private final InternalLRUcache<k, v> internalLRUcache;


    public LinkedHashLRUcache(int limit) {
        Assert.state(limit > 0, "limit必须大于0");
        this.limit = limit;
        this.internalLRUcache = new InternalLRUcache(limit);
    }


 
    public void put(k key, v value) {
        this.internalLRUcache.put(key, value);
    }

    public v get(k key) {
        return this.internalLRUcache.get(key);
    }

    public void remove(k key) {
        this.internalLRUcache.remove(key);
    }

    public int size() {
        return this.internalLRUcache.size();
    }

    public void clear() {
        this.internalLRUcache.clear();
    }

    public String toString() {
        return internalLRUcache.toString();
    }
}

当存在热点数据时,LRU的效率很好,但偶发性的、周期性的批量操作会导致LRU命中率急剧下降,缓存污染情况比较严重。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值