阿里巴巴笔试考到了LRU,一激动忘了怎么回事了。。准备不充分啊。。

缓存这个东西就是为了提高运行速度的,由于缓存是在寸土寸金的内存里面,不是在硬盘里面,所以容量是很有限的。LRU这个算法就是把最近一次使用时间离现在时间最远的数据删除掉。先说说List:每次访问一个元素后把这个元素放在 List一端,这样一来最远使用的元素自然就被放到List的另一端。缓存满了t的时候就把那最远使用的元素remove掉。但更实用的是HashMap。因为List太慢,要删掉的数据总是位于List底层数组的第一个位置,删掉之后,后面的数据要向前补位。。所以复杂度是O(n),那就用链表结构的LinkedHashMap呗~,LinkedHashMap默认的元素顺序是put的顺序,但是如果使用带参数的构造函数,那么LinkedHashMap会根据访问顺序来调整内部 顺序。 LinkedHashMap的get()方法除了返回元素之外还可以把被访问的元素放到链表的底端,这样一来每次顶端的元素就是remove的元素。

构造函数如下:

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

initialCapacity   初始容量

loadFactor    加载因子,一般是 0.75f

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

来个例子吧:
import java.util.*;

class Test
{
public static void main(String[] args) throws Exception{ Map<Integer,Integer> map=new LinkedHashMap<>(10,0.75f,true);
map.put(9,3);
map.put(7,4);
map.put(5,9);
map.put(3,4);
//现在遍历的话顺序肯定是9,7,5,3
//下面访问了一下9,3这个键值对,输出顺序就变喽~
map.get(9);
for(Iterator<Map.Entry<Integer,Integer>> it=map.entrySet().iterator();it.hasNext();){
System.out.println(it.next().getKey());
}
}
}

输出

7
5
3
9
好玩吧~
下面开始实现LRU缓存喽~
import java.util.*;
//扩展一下LinkedHashMap这个类,让他实现LRU算法
class LRULinkedHashMap<K,V> extends LinkedHashMap<K,V>{
//定义缓存的容量
private int capacity;
private static final long serialVersionUID = 1L;
//带参数的构造器
LRULinkedHashMap(int capacity){
//调用LinkedHashMap的构造器,传入以下参数
super(16,0.75f,true);
//传入指定的缓存最大容量
this.capacity=capacity;
}
//实现LRU的关键方法,如果map里面的元素个数大于了缓存最大容量,则删除链表的顶端元素
@Override
public boolean removeEldestEntry(Map.Entry<K, V> eldest){
System.out.println(eldest.getKey() + "=" + eldest.getValue());
return size()>capacity;
}
}
//测试类
class Test{
public static void main(String[] args) throws Exception{ //指定缓存最大容量为4
Map<Integer,Integer> map=new LRULinkedHashMap<>(4);
map.put(9,3);
map.put(7,4);
map.put(5,9);
map.put(3,4);
map.put(6,6);
//总共put了5个元素,超过了指定的缓存最大容量
//遍历结果
for(Iterator<Map.Entry<Integer,Integer>> it=map.entrySet().iterator();it.hasNext();){
System.out.println(it.next().getKey());
}
}
}

输出结果如下

9=3
9=3
9=3
9=3
9=3
7
5
3
6
分析一下:使用带参数构造器,且启用LRU模式的LinkedHashMap会在每次有新元素加入的时候,判断当前储存元素是否超过了缓存上限,也就是执行
一次removeEldestEntry方法,看最后的遍历结果,发现果然把9删除了,LRU发挥作用了~

如何用LinkedHashMap实现LRU缓存算法的更多相关文章

  1. LinkedHashMap实现LRU缓存算法

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

  2. 总是套路留人心, JAVA提供的套路: LinkedHashMap实现LRU缓存; InvocationHandler实现动态代理; fork/join实现窃取算法

    1. LinkedHashMap实现LRU缓存 LRU缓存核心是根据访问顺序排序, 自动移除队尾缓存, LinkedHashMap已经实现了这些要求: public LRUCache<K, V& ...

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

    好吧,有人可能觉得我标题党了,但我想告诉你们的是,前阵子面试确实挂在了 RLU 缓存算法的设计上了.当时做题的时候,自己想的太多了,感觉设计一个 LRU(Least recently used) 缓存 ...

  4. LinkedHashMap 实现LRU缓存

    date: 2020-07-09 13:52:00 updated: 2020-07-21 17:40:00 LinkedHashMap 实现LRU缓存 参考 LinkedHashMap是HashMa ...

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

    今天我们来深入探索一下LinkedHashMap的底层原理,并且使用linkedhashmap来实现LRU缓存. 摘要: HashMap和双向链表合二为一即是LinkedHashMap.所谓Linke ...

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

    import java.util.Hashtable; class DLinkedList { String key; //键 int value; //值 DLinkedList pre; //双向 ...

  7. come on! 基于LinkedHashMap实现LRU缓存

    /** * @Description 基于LinkedHashMap实现一个基于'LRU最近最少使用'算法的缓存,并且最多存MAX个值 * @Author afei * @date:2021/4/25 ...

  8. LRU缓存算法与pylru

    这篇写的略为纠结,算法原理.库都是现成的,我就调用了几个函数而已,这有啥好写的?不过想了想,还是可以介绍一下LRU算法的原理及简单的用法.   LRU(Least Recently Used,最近最少 ...

  9. Java 自定义实现 LRU 缓存算法

    背景 LinkedHashMap继承自HashMap,内部提供了一个removeEldestEntry方法,该方法正是实现LRU策略的关键所在,且HashMap内部专门为LinkedHashMap提供 ...

随机推荐

  1. php部分学习笔记

    [web 开发分为]1. 静态web 开发(html 页面) 如果我们的一个页面,始终是一成不变的,则就是属于静态web 开发,一般讲用html 技术就ok2. 动态web 开发 比如: 我们需要发帖 ...

  2. hdu 2685 I won't tell you this is about number theory 数论

    题目链接 根据公式 \[ gcd(a^m-1, a^n-1) = a^{gcd(m, n)}-1 \] 就可以很容易的做出来了. #include <iostream> #include ...

  3. MVC3 带查询的分页Helper

    接上篇mvc3 分页Helper. 带查询的分页Helper是在上一篇分页的基础上来的.下面看代码: 首先,在System.Web.Mvc命名空间下的自定义类HtmlPage下面添加一个用于处理“查询 ...

  4. TLC是什么

    TLC = Triple-Level Cell,即3bit/cell,它的寿命短,速度慢,约500-5000次擦写寿命. 现在U盘多为MLC,TLC也有一部分,将来TLC会占大部分市场. 一种名为TL ...

  5. Win32中安全的子类化(翻译)

    关于子类化的话题虽然有些旧,但它至今仍然不失为一种开发Windows的强有力技术,在MFC的内核.甚至.NET的内核中都离不开它,希望本连载能对Windows开发的爱好者有所帮助. 原文标题:Safe ...

  6. idea破解码

    43B4A73YYJ-eyJsaWNlbnNlSWQiOiI0M0I0QTczWVlKIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYXNzaWduZWVOYW1lIjoiI ...

  7. C++ Placement New

    先看一个题目: #include <stdio.h> #include <iostream> using namespace std; struct Base { int j; ...

  8. centos 6.7 perl 5.22 安装DBD 需要使用老的perl版本

    zjzc01:/usr/bin# mv perl.bak perlold zjzc01:/usr/bin# cd zjzc01:/root# cd DBD-Oracle-1.36 zjzc01:/ro ...

  9. Android中ViewStub组件使用

    1. 概述: ViewStub组件和<include>标签的作用类似,主要是为了提高布局的重用性,及布局的模块化.它们之间最大的差别是,ViewStub中的布局不会随着它所在布局的渲染而渲 ...

  10. poj 2540 Hotter Colder 切割多边形

    /* poj 2540 Hotter Colder 切割多边形 用两点的中垂线切割多边形,根据冷热来判断要哪一半 然后输出面积 */ #include <stdio.h> #include ...