一。LRU算法简介

LRU(Least Recently Used)最近最久未使用算法

常见应用场景:内存管理中的页面置换算法、缓存淘汰中的淘汰策略等

二。实现理论

  底层结构:双向链表 + HashMap ,双向链表由特定的哈希节点组成。

(1)访问节点时,将其从原来位置删除,插入到双向链表头部;
(2)更新节点时,先删除原有缓存数据(即原有节点),然后更新map映射,再将更新值作为节点插入链表头;更新后,判断容量是否超过最大内存使用量
(3)超过则执行淘汰;淘汰即删除双向链表最后一个节点,同时删除map中的映射
(4)LRU实现中有频繁的查找节点并删除,为节省时间(链表查找目标节点需要遍历),使用HashMap保存键-节点映射关系,O(1)的查找+O(1)的删除
(5)LRU实现中,要频繁的在头部插入,以及在尾部删除;因此,需要定义head、tail两个节点,方便操作
 
三。代码
  1. package com.xl.Base;
  2.  
  3. import java.util.HashMap;
  4. import java.util.Iterator;
  5.  
  6. /**
  7. * 最近最久未使用淘汰策略
  8. * 基于 双向链表 + 哈希表组成,其中双向链表由哈希链表节点构成
  9. * 封装为 LRU(K, V)
  10. * 对外提供 get(K)访问数据、put(K, V)更新数据、Iterator()遍历数据
  11. */
  12. public class LRU<K, V> implements Iterable<K>{
  13.  
  14. private Node head;
  15. private Node tail;
  16. //记录K-Node映射,便于快速查找目标数据对应节点
  17. private HashMap<K, Node> map;
  18. private int maxSize;
  19.  
  20. //哈希链表节点类 Node
  21. private class Node{
  22. Node pre;
  23. Node next;
  24. K k;
  25. V v;
  26.  
  27. //Node对外提供构造方法
  28. public Node(K k, V v) {
  29. this.k = k;
  30. this.v = v;
  31. }
  32. }
  33.  
  34. //初始化时必须传入最大可用内存容量
  35. public LRU(int maxSize){
  36. this.maxSize = maxSize;
  37. //HashMap初始容量设置为 maxSize * 4/3,即达到最大可用内存时,HashMap也不会自动扩容浪费空间
  38. this.map = new HashMap<>(maxSize * 4 / 3);
  39.  
  40. head.next = tail;
  41. tail.pre = head;
  42. }
  43.  
  44. //获取指定数据
  45. private V get(K key) {
  46. //判断是否存在对应数据
  47. if(!map.containsKey(key)) {
  48. return null;
  49. }
  50.  
  51. //最新访问的数据移动到链表头
  52. Node node = map.get(key);
  53. remove(node);
  54. addFirst(node);
  55. return node.v;
  56. }
  57.  
  58. //更新旧数据或添加数据
  59. private void put(K key, V value) {
  60. //若存在旧数据则删除
  61. if(map.containsKey(key)) {
  62. Node node = map.get(key);
  63. remove(node);
  64. }
  65.  
  66. //新数据对应节点插入链表头
  67. Node node = new Node(key, value);
  68. map.put(key, node);
  69. addFirst(node);
  70.  
  71. //判断是否需要淘汰数据
  72. if(map.size() > maxSize) {
  73. removeLast();
  74. //数据节点淘汰后,同时删除map中的映射
  75. map.remove(node.k);
  76. }
  77. }
  78.  
  79. //将指定节点插入链表头
  80. private void addFirst(Node node) {
  81. Node next = head.next;
  82.  
  83. head.next = node;
  84. node.pre = head;
  85.  
  86. node.next = next;
  87. next.pre = node;
  88. }
  89.  
  90. //从链表中删除指定节点
  91. private void remove(Node node) {
  92. Node pre = node.pre;
  93. Node next = node.next;
  94.  
  95. pre.next = next;
  96. next.pre = pre;
  97.  
  98. node.next = null;
  99. node.pre = null;
  100. }
  101.  
  102. //淘汰数据
  103. private Node removeLast() {
  104. //找到最近最久未使用的数据所对应节点
  105. Node node = tail.pre;
  106.  
  107. //淘汰该节点
  108. remove(node);
  109.  
  110. return node;
  111. }
  112.  
  113. //通过迭代器遍历所有数据对应键
  114. @Override
  115. public Iterator<K> iterator() {
  116. return new Iterator<K>() {
  117.  
  118. private Node cur = head.next;
  119.  
  120. @Override
  121. public boolean hasNext() {
  122. return cur != tail;
  123. }
  124.  
  125. @Override
  126. public K next() {
  127. Node node = cur;
  128. cur = cur.next;
  129. return node.k;
  130. }
  131.  
  132. };
  133. }
  134.  
  135. }

Java实现LRU算法的更多相关文章

  1. Redis 笔记整理:回收策略与 LRU 算法

    Redis的回收策略 noeviction:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令,但DEL和几个例外) allkeys-lru: 尝试回收最少使用的键(L ...

  2. LRU算法的Java实现

    LRU全称是Least Recently Used,即最近最久未使用的意思. LRU算法的设计原则是:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小.也就是说,当限定的空间已 ...

  3. 使用java.util.LinkedList模拟实现内存页面置换算法--LRU算法

    一,LRU算法介绍 LRU是内存分配中“离散分配方式”之分页存储管理方式中用到的一个算法.每个进程都有自己的页表,进程只将自己的一部分页面加载到内存的物理块中,当进程在运行过程中,发现某页面不在物理内 ...

  4. LRU算法介绍和在JAVA的实现及源码分析

    一.写随笔的原因:最近准备去朋友公司面试,他说让我看一下LRU算法,就此整理一下,方便以后的复习. 二.具体的内容: 1.简介: LRU是Least Recently Used的缩写,即最近最少使用. ...

  5. 近期最久未使用页面淘汰算法———LRU算法(java实现)

    请珍惜小编劳动成果,该文章为小编原创,转载请注明出处. LRU算法,即Last Recently Used ---选择最后一次訪问时间距离当前时间最长的一页并淘汰之--即淘汰最长时间没有使用的页 依照 ...

  6. 最近最久未使用页面淘汰算法———LRU算法(java实现)

    请珍惜小编劳动成果,该文章为小编原创,转载请注明出处. LRU算法,即Last Recently Used ---选择最后一次访问时间距离当前时间最长的一页并淘汰之--即淘汰最长时间没有使用的页 按照 ...

  7. Android图片缓存之Lru算法

    前言: 上篇我们总结了Bitmap的处理,同时对比了各种处理的效率以及对内存占用大小.我们得知一个应用如果使用大量图片就会导致OOM(out of memory),那该如何处理才能近可能的降低oom发 ...

  8. 缓存淘汰算法--LRU算法

    1. LRU1.1. 原理 LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是"如果数据最近被访问过,那么将来被访问的几率也 ...

  9. 借助LinkedHashMap实现基于LRU算法缓存

    一.LRU算法介绍 LRU(Least Recently Used)最近最少使用算法,是用在操作系统中的页面置换算法,因为内存空间是有限的,不可能把所有东西都放进来,所以就必须要有所取舍,我们应该把什 ...

随机推荐

  1. 2018-4-25 1.如何在GitHub上新建一个新的项目并下载该项目及如何提交新的文件

  2. awk积累

    1. 计算一个文本中每一列的和 [root@centos ~]# cat aaa.txt [root@centos ~]# awk 'BEGIN{a=0;b=0;c=0}{a+=$1;b+=$2;c+ ...

  3. WCF nginx反向代理遇到的问题

    正常配置了nginx反向代理,其他java站点什么的都正常,就wcf总是失败.始终会跑如下异常: 由于 AddressFilter 在 EndpointDispatcher 不匹配,To 为“http ...

  4. Android零基础入门第78节:四大组件的纽带——Intent

    前面学习Activity时己经多次使用了 Intent,当一个Activity需要启动另一个Activity时, 程序并没有直接告诉系统要启动哪个Activity,而是通过Intent来表达自己的意图 ...

  5. ef调用 access

    <add name="AccessConnection" connectionString="Provider=Microsoft.ACE.OleDb.12.0;D ...

  6. CNN(卷积神经网络)、RNN(循环神经网络)和DNN(深度神经网络)

    本文转载修改自:知乎-科言君 感知机(perceptron) 神经网络技术起源于上世纪五.六十年代,当时叫感知机(perceptron),拥有输入层.输出层和一个隐含层.输入的特征向量通过隐含层变换达 ...

  7. msys2 安装笔记(可以按照这个关键字搜索)

    以前一直在用 msys,最近发现还有个 msys2,并且msys2 配套的编译器是MinGW-w64. 就试着用了用,感觉还不错,这里把安装过程记录一下. 简单的说,MSYS2 是MSYS的一个升级版 ...

  8. SYN5301型 毫秒表时间检定仪

       SYN5301型  毫秒表时间检定仪 频率记录仪时间记录仪时间频率信号的精密测量使用说明视频链接; http://www.syn029.com/h-pd-76-0_310_6_-1.html 请 ...

  9. BDC

    TC:SHDB 复制到应用处并更改参数. 附上部分代码 *       Batchinputdata of single transaction DATA:   bdcdata LIKE bdcdat ...

  10. Redis 学习笔记(篇二):字典

    字典 字典又称为符号表.关联数组或映射(map),是一种用于保存键值对(key-value)的数据结构. 那么 C 语言中有没有这样 key-value 型的内置数据结构呢? 答案:没有. 说起键值对 ...