📗
Notes
  • Introduction
  • Files
  • Android
    • Http
      • Http基础
      • Okhttp理解
    • Jetpack
      • Notes
  • Java ways
    • 101
      • Basis
        • Index
        • Front
          • Angular
            • Angular start 01
            • Angular start 02
          • Typescript
            • Index
            • Ts 01
        • Java
          • Concurrency
          • Frameworks
            • Jdbc与连接池
            • Rxjava基础
            • Spring框架基础
          • Sugar&skill
        • Tool
          • Docker
            • Docker basis
            • Kubernetes play
          • Git
            • Git basic
          • Vim
            • Vim advance
      • Cs
        • Imp
          • Lru
          • Index
    • Snippets
      • Jpa和spring系列注解表
      • Java与oracle数据库各种操作
      • Maven初始化template
      • Nginx配置
      • Nginx反代后配置自动ssl续签
      • 终端033颜色
    • Ways
      • Java ways 01
      • Interview
        • Question
        • Requirements
      • Leetcode101
        • Acwing
          • Index
          • 背包问题
        • Explores
        • Solutions
          • Algorithms
            • Index
          • Concurrency
            • Index
          • Shell
            • Index
          • Sql
            • Index
  • Leecode
    • 牛客
      • 剑指offer
  • Play
    • Youtube离线下载
  • Python basic notes
    • Python days
Powered by GitBook
On this page
  • LRU 算法实现
  • 具体实现
  • References

Was this helpful?

  1. Java ways
  2. 101
  3. Cs
  4. Imp

Lru

PreviousImpNextIndex

Last updated 4 years ago

Was this helpful?

   Author: Gentleman.Hu
   Create Time: 2020-10-19 17:35:22
   Modified by: Gentleman.Hu
   Modified time: 2020-10-20 15:01:46
   Email: justfeelingme@gmail.com
   Home: https://crushing.xyz
   Description: LRU算法实现

LRU 算法实现

Least Recently Used

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

  • 实现方法 1. 用一个数组存储数据,给每个数据项标记一个访问时间戳,每次插入新数据项的时候,先把数组中存在的数据项的时间戳自增,并将新数据项的时间戳置为0并插入到数组中.每次访问数组中的数据项的时候,将被访问的数据项的时间戳置为0.当数据空间已满时,将时间戳最大的数据项淘汰. 2. 利用一个链表实现,每次新插入数据的时候将新数据插到链表的头部;每次缓存命中(数据被访问),则将数据移到链表头部;那么当链表满的时候,就将表尾部的数据丢弃. 3. 利用链表和hashmap.当需要插入新得数据项的时候,如果新数据项在链表中存在(命中),则把该节点移动到链表头部,如果不存在,则新建节点,放在链表头部,若缓存满了,则把链表最后一个节点删除即可.在访问数据的时候,如果数据项在链表中存在,则把该节点移动到链表头部,否则返回-1.这样链表尾部节点就是最近最久未访问数据项.

  • 评价 1. 需要不停维护数据项访问时间戳,insert,delete和访问数据时间复杂度都是O(n). 2. 链表在定位数据时候时间复杂度为O(n).

实际多采用第三种实现

  • LRU算法对比

对比点

对比

命中率

LRU-2 > MQ(2) > 2Q > LRU

复杂度

LRU-2 > MQ(2) > 2Q > LRU

代价

LRU-2 > MQ(2) > 2Q > LRU

具体实现

  1. LinkedHashMap实现

public class LRU<K,V>{
  private static final float hashLoadFactory = 0.75f;
  private LinkedHashMap<K,V> map;
  private int cacheSize;

  public LRU(int cacheSize){
    this.cacheSize = cacheSize;
    // Math.ceil(double x) - 返回参数值的
    int capacity = (int)Math.ceil(cacheSize/hashLoadFactory)+1;
    map = new LinkedHashMap<K,V>(capacity,hashLoadFactory,true){
      private static final long serialVersionUID = 1L;

      @Override
      protected boolean removeEldestEntry(Map.Entry eldest){
        return size()>LRU.this.cacheSize;
      }
    };
  }

  public synchronized V get(K key){
    return map.get(key);
  }

  public synchronized void put(K key,V value){
    map.put(key,value);
  }

  public synchronized void clear(){
    map.clear();
  }
}

References

  • Math.ceil()和Math.floor()和Math.round()区别

这三个方法分别遵循下列舍入规则:

  • Math.ceil()执行向上舍入,即它总是将数值向上舍入为最接近的整数;

  • Math.floor()执行向下舍入,即它总是将数值向下舍入为最接近的整数;

  • Math.round()执行标准舍入,即它总是将数值四舍五入为最接近的整数(这也是我们在数学课上学到的舍入规则)。

source_from_csdn