LinkedHashMap实现LRU缓存算法

LinkedHashMap的get()方法除了返回元素之外还可以把被访问的元素放到链表的底端,这样一来每次顶端的元素就是remove的元素

构造函数如下:

public LinkedHashMap (int initialCapacity, float loadFactor, boolean accessOrder);

initialCapacity   初始容量

loadFactor    加载因子,一般是 0.75f

accessOrder   false基于插入顺序,true 基于访问顺序(get一个元素后,这个元素被加到最后,使用了LRU 最近最少被使用的调度算法)

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 该类是线程安全的带有容量限制的LinkedHashMap
 * 超容量的元素采用LRU方式删除
 * 线程安全仅限于已经覆盖的几个方法,若有其他需要可自行添加
 * 迭代操作不保证数据的一致性,即使remove方法是线程安全的也会抛ConcurrentModificationException
 */
public class LinkedMapLRU<K, V> extends LinkedHashMap<K, V> {
    private static final long serialVersionUID = -7911712053305433954L;

    private int capacity;
    private final ReentrantLock lock = new ReentrantLock();

    public LinkedMapLRU(int capacity) {
        super(capacity, 0.75f, true);
        this.capacity = capacity;
    }
    @Override
    public V put(K key, V value) {
        try {
            lock.lock();
            return super.put(key, value);
        } finally {
            lock.unlock();
        }
    }
    @Override
    public V get(Object key) {
        try {
            lock.lock();
            return super.get(key);
        } finally {
            lock.unlock();
        }
    }
    @Override
    public V remove(Object key) {
        try {
            lock.lock();
            return super.remove(key);
        } finally {
            lock.unlock();
        }
    }

    @Override
    public boolean removeEldestEntry(Map.Entry<K,V> eldest) {
        if(size() > capacity) {            System.out.println(eldest.getKey() +":" + eldest.getValue());
            return true;
        }
        return false;
    }

    public void setMaxSize(int size) {
        this.capacity = size;
    }

}

测试类:

LinkedMapLRU<Integer, Integer>  LRU = new LinkedMapLRU<Integer, Integer>(3);
        LRU.put(3, 1);
        LRU.put(6, 2);
        LRU.put(9, 3);
        LRU.get(3); //key=3移到顶部
        LRU.put(12, 4);
        LRU.put(15, 5);
        for(Map.Entry<Integer, Integer> entry : LRU.entrySet()) {
            System.out.println(entry.getKey() + " " +entry.getValue());
        }

测试结果:

6:2
9:3
3 1
12 4
15 5

原文地址:https://www.cnblogs.com/cherish010/p/8423093.html

时间: 2024-08-27 15:36:57

LinkedHashMap实现LRU缓存算法的相关文章

基于LinkedHashMap实现LRU缓存调度算法原理

引言 本文就 <基于LinkedHashMap实现LRU缓存调度算法原理及应用 >一文作为材料,记录一些常见问题,备忘. 延伸出两道常见的Java面试题: 插入Entry节点到table表的链表中时,Hashmap 和LinkedHashmap使用头茶法还是尾茶法?遍历map的时候,Entry.Entryset()获取的set集合,是按照从头到尾还是从尾到头的顺序存储的? 实现LRU算法最合适的数据结构? 如果读者可以打出来,不用继续看下边的资料了.初学者请继续阅读.相信你读完之后可以找到问题

说说Android LRU缓存算法实现笔记(二)--LRU的应用

上一篇文章说说Android LRU缓存算法实现学习笔记(一) 中我们介绍了最常用的实现LRU缓存的数据结构LinkedHashMap,这一节我们会针对LinkedHashMap的数据结构的特性,来自己实现缓存结构和学习Android源码和项目中对缓存的完善. 上一篇说到对于缓存实现,我们很重要的会考虑以下几点:1.访问速度:2.逐出旧的缓存策略:3.最好还能考虑到一定的并发度.LinkedHashMap对哈希表的实现保证了我们缓存的快速访问速度,我们通过源码知道,LinkedHashMap默认

Java集合详解5:深入理解LinkedHashMap和LRU缓存

Java集合详解5:深入理解LinkedHashMap和LRU缓存 今天我们来深入探索一下LinkedHashMap的底层原理,并且使用linkedhashmap来实现LRU缓存. 具体代码在我的GitHub中可以找到 https://github.com/h2pl/MyTech 文章首发于我的个人博客: https://h2pl.github.io/2018/05/11/collection5 更多关于Java后端学习的内容请到我的CSDN博客上查看:https://blog.csdn.net

面试挂在了 LRU 缓存算法设计上

好吧,有人可能觉得我标题党了,但我想告诉你们的是,前阵子面试确实挂在了 RLU 缓存算法的设计上了.当时做题的时候,自己想的太多了,感觉设计一个 LRU(Least recently used) 缓存算法,不会这么简单啊,于是理解错了题意(我也是服了,还能理解成这样,,,,),自己一波操作写了好多代码,后来卡住了,再去仔细看题,发现自己应该是理解错了,就是这么简单,设计一个 LRU 缓存算法. 不过这时时间就很紧了,按道理如果你真的对这个算法很熟,十分钟就能写出来了,但是,自己虽然理解 LRU

说说Android LRU缓存算法实现学习笔记(一)

在我们的手机应用开发时候,我们经常会遇到大数据访问的时候,我们通常会考虑以下几个方面的情况.一.手机内存的限制还必须保证应用反应的流畅:二.尽量小的流量消耗,不然,你的应用流畅度再好体验再好,用户还是会毫不犹豫的卸载掉你的应用.大数据量访问的情况下,数据缓存是我们一定会考虑到的解决方案.而作为缓存,我们很重要的会考虑以下几点:1.访问速度:2.逐出旧的缓存策略:3.最好还能考虑到一定的并发度.这篇我们主要说说LRU策略的缓存算法实现,我们就用图片缓存为例来谈谈Android应用开发中的缓存实现.

LRU缓存算法

引子: 我们平时总会有一个电话本记录所有朋友的电话,但是,如果有朋友经常联系,那些朋友的电话号码不用翻电话本我们也能记住,但是,如果长时间没有联系了,要再次联系那位朋友的时候,我们又不得不求助电话本,但是,通过电话本查找还是很费时间的.但是,我们大脑能够记住的东西是一定的,我们只能记住自己最熟悉的,而长时间不熟悉的自然就忘记了. 其实,计算机也用到了同样的一个概念,我们用缓存来存放以前读取的数据,而不是直接丢掉,这样,再次读取的时候,可以直接在缓存里面取,而不用再重新查找一遍,这样系统的反应能力

LRU缓存算法与pylru

这篇写的略为纠结,算法原理.库都是现成的,我就调用了几个函数而已,这有啥好写的?不过想了想,还是可以介绍一下LRU算法的原理及简单的用法. LRU(Least Recently Used,最近最少使用)是一种内存页面置换算法.什么叫内存页面置换?我们知道,相对于内存的速度来讲,磁盘的速度是很慢的.我们需要查询数据的时候,不能每次都跑到磁盘去查,需要在内存里设置一块空间,把一些常用的数据放在这块空间里,以后查的时候就直接在这里查,而不必去磁盘,从而起到“加速”的作用.但是这块空间肯定是远远小于磁盘

HashMap+双向链表手写LRU缓存算法/页面置换算法

import java.util.Hashtable; //https://zhuanlan.zhihu.com/p/34133067 class DLinkedList { String key; //键 int value; //值 DLinkedList pre; //双向链表前驱 DLinkedList next; //双向链表后继 } public class LRUCache { private Hashtable<String,DLinkedList> cache = new H

LRU缓存实现(Java)

LRU Cache的LinkedHashMap实现 LRU Cache的链表+HashMap实现 LinkedHashMap的FIFO实现 调用示例 LRU是Least Recently Used 的缩写,翻译过来就是"最近最少使用",LRU缓存就是使用这种原理实现,简单的说就是缓存一定量的数据,当超过设定的阈值时就把一些过期的数据删除掉,比如我们缓存10000条数据,当数据小于10000时可以随意添加,当超过10000时就需要把新的数据添加进来,同时要把过期数据删除,以确保我们最大缓