算法-使用数组实现LRU

哒哒队长

思路

  • 每次放值时先判断是否在已经在缓存中

    • 如果是,将它左边的元素全部右移一个,然后放置在数组头中,同时更新map中角标
    • 如果不是,判断数组是否还有空间

      • 有空间,将全部元素右移,然后放置在数组头中,同时更新map中角标
      • 如果没有,将角标0到数组长度-1的元素右移,然后放置在数组头中,同时更新map中角标,并在map中删除刚才的元素

关键点

使用map维护数组中值与角标的对应关系,避免每次遍历数组

实现

package com.jiaotd.lru.array;

import java.util.HashMap;
import java.util.Map;

/**
 * 
 * 
 * @author Administrator
 *
 */
public class ArrayLRU<T> {

    private int length;
    private int pos = 0;

    private T[] array1;
    private Map<T, Integer> cache;

    public ArrayLRU(int length) {
        this.length = length;
        array1 = (T[]) new Object[length];
        cache = new HashMap<T, Integer>(length);
    }

    public ArrayLRU<T> add(T data) {
        Integer index = cache.get(data);
        // 之前没有缓存
        if (null == index) {
            if (pos < length) {
                rightMove(pos);
                array1[0] = data;
                cache.put(data, 0);
                pos++;
            } else {
                rightMove(pos - 1);
                cache.remove(array1[length - 1]);
                array1[0] = data;
                cache.put(data, 0);
            }

        } else {
            // 之前有缓存
            rightMove(index);
            array1[0] = data;
            cache.put(data, 0);
        }

        return this;
    }

    public void rightMove(int end) {
        for (int i = end - 1; i >= 0; i--) {
            array1[i + 1] = array1[i];
            cache.put(array1[i + 1], i + 1);
        }
    }

    public void print() {
        for (int i = 0; i < pos; i++) {
            System.out.print(array1[i] + ",");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        ArrayLRU<Integer> arrayLRU = new ArrayLRU<Integer>(8);
        arrayLRU.add(0).add(1).add(2).add(3).add(4).add(5).add(6).add(7);
        arrayLRU.print();
        arrayLRU.add(3);
        arrayLRU.print();
        arrayLRU.add(10);
        arrayLRU.print();
        arrayLRU.add(5);
        arrayLRU.print();
        arrayLRU.add(11);
        arrayLRU.print();
    }

}

结果

7,6,5,4,3,2,1,0,
3,7,6,5,4,2,1,0,
10,3,7,6,5,4,2,1,
5,10,3,7,6,4,2,1,
11,5,10,3,7,6,4,2,
阅读 3.1k

7 声望
0 粉丝
0 条评论
推荐阅读
Liquibase 数据库版本管理工具:3. changeSet 变更集详解
上篇文章中详细了介绍了一下changelog 文件的使用,本篇文章将详细说一下 changeSet 变更集 中的细节,以及通常的使用方式 1.变更集分类 changeSet 分为 6类: add create drop rename sql other 官方文档:[链接...

哒哒队长1阅读 3.8k评论 1

【已结束】SegmentFault 思否技术征文丨浅谈 Java 进阶之路
本期中奖名单:[链接]亲爱的开发者们:大家好,我是 SegmentFault 思否的社区管理员思否小姐姐 ~ 我们的社区征文活动再次起航,这一次,想邀请作者们分享原创技术内容。将于 9-12 月会相继上线技术专题征文活动,...

SegmentFault思否9阅读 4.4k评论 20

封面图
10分钟教你写一个数据库
今天教大家借助一款框架快速实现一个数据库,这个框架就是Calcite,下面会带大家通过两个例子快速教会大家怎么实现,一个是可以通过 SQL 语句的方式可以直接查询文件内容,第二个是模拟 Mysql 查询功能,以及最后...

艾小仙8阅读 2.1k评论 1

从前端到全栈 -- 最全面向对象总结
从事前端的这两年中,也接触了后端领域,像 PHP Node, 并且都用它们做过一些 demo 和 私活 ,站在职业发展道路上来讲,了解后端是好的,自己可以熟练前后的开发流程,整条链路下来,很清晰,懂了后端,在自己以后...

程序员海军8阅读 2.1k

封面图
性能优化必备——火焰图
本文主要介绍火焰图及使用技巧,学习如何使用火焰图快速定位软件的性能卡点。结合最佳实践实战案例,帮助读者加深刻的理解火焰图构造及原理,理解 CPU 耗时,定位性能瓶颈。

咕咕鸡7阅读 1.9k

封面图
我终于会写 Java 的定时任务了!
前言学过定时任务,但是我忘了,忘得一干二净,害怕,一直听别人说:你写一个定时任务就好了。写个定时任务让他去爬取就行了。我不会,所以现在得补回来了,欠下的终究要还的,/(ㄒoㄒ)/~~定时任务是什么?大家都...

god23bin8阅读 1.4k

封面图
记录一个关于 GBK 编码的问题
UTF-8 是一种国际化的编码方式,包含了世界上大部分的语种文字(简体中文字、繁体中文字、英文、日文、韩文等语言),也兼容 ASCII 码。

编程码农5阅读 1.2k

7 声望
3 粉丝
宣传栏