简易LRU缓存淘汰模拟

模拟采用链表保存缓存数据,功能如下

1. 新数据插入到链表头部;

2. 每当缓存命中(即缓存数据被访问),则将数据移到链表头部;

3. 当链表满的时候,将链表尾部的数据丢弃。

假设访问的数据为 Person

public class LRUCache{

    private static int count=0;
    private int capacity;
    private static class Node{
        private static Node head;
        private static Node tail;
        private Person person;
        private Node prev;
        private Node next;

        public Node(Person person){
            this.person = person;
        }
    }

    public void iterator(){
        Node h = Node.head;
        while (h!=null){
            System.out.println(h.person.getId()+" "+h.person.getName());
            h = h.next;
        }
    }

    public LRUCache(int capacity){
        this.capacity = capacity;
    }

    public Person getPersonById(int id){
        Node h = Node.head;
        if (h==null)return null;
        while (h!=null){
            if (h.person.getId() == id){
                Person target = h.person;
                moveToHead(h.person);
                deleteNode(h);
                return target;
            }
            h = h.next;
        }
        return null;
    }

    public void addToList(Person person){
        if (capacity == count){
            Node.tail =  Node.tail.prev;
            Node.tail.next = null;
        }
        moveToHead(person);
        count++;
    }

    private void moveToHead(Person person){
        if (Node.head == null){
            Node newNode = new Node(person);
            Node.head = newNode;
            Node.tail = newNode;
            return;
        }
        Node h = Node.head;
        Node newNode = new Node(person);
        newNode.next = h;
        h.prev = newNode;
        Node.head = newNode;
    }

    private void deleteNode(Node node){
        if (node == Node.head){
            Node.head = node.next;
            Node.head.prev = null;
        }

        if (node == Node.tail){
            Node.tail =  node.prev;
            Node.tail.next = null;
        }
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }
}

模拟获取数据:

public class PersonList {

    private LRUCache cache;
    public PersonList(LRUCache lruCache){
        this.cache = lruCache;
    }

    public LRUCache getCache(){
        return cache;
    }

    public Person getPersonById(int id){
        Person p;
        if ((p = cache.getPersonById(id) )== null){
            //模拟假设从数据库中根据id查出对应的人
            p= new Person(id,"p"+id,18,1);
            cache.addToList(p);
        }
        return p;
    }
}

运行:

public class Test {

    public static void main(String[] args){

        PersonList personList = new PersonList(new LRUCache(3));
        Person p1 = personList.getPersonById(1);
        personList.getCache().iterator();
        System.out.println("-------------------");
        Person p2 = personList.getPersonById(2);
        personList.getCache().iterator();
        System.out.println("-------------------");
        Person p3 = personList.getPersonById(3);
        personList.getCache().iterator();
        System.out.println("-------------------");
        Person p5 = personList.getPersonById(2);
        personList.getCache().iterator();
        System.out.println("-------------------");
        Person p4 = personList.getPersonById(4);
        personList.getCache().iterator();

    }

运行结果:1 p1-------------------2 p21 p1-------------------3 p32 p21 p1-------------------2 p23 p31 p1-------------------4 p42 p23 p3

LRU有好多种实现的方式,一般可以用双链表+hashtable,如果只用双链表的话,查找的时间复杂度为O(n),效率较慢

原文地址:https://www.cnblogs.com/zwb1/p/12180804.html

时间: 2024-10-11 18:00:13

简易LRU缓存淘汰模拟的相关文章

06 | 链表(上):如何实现LRU缓存淘汰算法?

我们先来讨论一个经典的链表应用场景,那就是 LRU 缓存淘汰算法. 缓存的大小有限,当缓存被用满时,哪些数据应该被清理出去,哪些数据应该被保留?这就需要缓存淘汰策略来决定. 常见的策略有三种: 先进先出策略 FIFO(First In,First Out).最少使用策略 LFU(Least Frequently Used).最近最少使用策略 LRU(Least Recently Used). 三种最常见的链表结构,它们分别是:单链表.双向链表和循环链表. 数组简单易用,在实现上使用的是连续的内存

Chapter 6 链表(上):如何实现LRU缓存淘汰算法?

缓存淘汰策略: 一.什么是链表? 1.和数组一样,链表也是一种线性表. 2.从内存结构来看,链表的内存结构是不连续的内存空间,是将一组零散的内存块串联起来,从而进行数据存储的数据结构. 3.链表中的每一个内存块被称为节点Node.节点除了存储数据外,还需记录链上下一个节点的地址,即后继指针next. 二.为什么使用链表?即链表的特点 1.插入.删除数据效率高O(1)级别(只需更改指针指向即可),随机访问效率低O(n)级别(需要从链头至链尾进行遍历). 2.和数组相比,内存空间消耗更大,因为每个存

Java简易LRU缓存实现(开发技巧)

威哥说:缓存与APP应用的关系,好比西门庆与色,根本就离不开,而且地位最重,所以,小白们想成为老鸟,对待缓存之情必需要深入,以下文章给你介绍了Java如果实现LRU(Least Recently Used)算法,即最近最少使用算法,这个算法在Android开发中被用于图片,内容的缓存,我在<Android核心技术(下)>课程中就详细讲解了LRU的全部实现,有兴趣的朋友可以登录扣丁学堂学习. 背景LinkedHashMap继承自HashMap,内部提供了一个removeEldestEntry方法

Java简易LRU缓存实现

背景 LinkedHashMap继承自HashMap,内部提供了一个removeEldestEntry方法,该方法正是实现LRU策略的关键所在,且HashMap内部专门为LinkedHashMap提供了3个专用回调方法,afterNodeAccess.afterNodeInsertion.afterNodeRemoval,这3个方法的字面意思非常容易理解,就是节点访问后.节点插入后.节点删除后分别执行的行为.基于以上行为LinkedHashMap就可以实现一个LRUCache的功能了. 实现 自

缓存淘汰算法--LRU算法

1. LRU1.1. 原理 LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是"如果数据最近被访问过,那么将来被访问的几率也更高". 1.2. 实现 最常见的实现是使用一个链表保存缓存数据,详细算法实现如下: 1. 新数据插入到链表头部: 2. 每当缓存命中(即缓存数据被访问),则将数据移到链表头部: 3. 当链表满的时候,将链表尾部的数据丢弃. 1.3. 分析 [命中率] 当存在热点数据时,LRU的效率很好,但偶发性的

缓存淘汰算法---LRU

1. LRU1.1. 原理 LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是"如果数据最近被访问过,那么将来被访问的几率也更高". 1.2. 实现 最常见的实现是使用一个链表保存缓存数据,详细算法实现如下: 1. 新数据插入到链表头部: 2. 每当缓存命中(即缓存数据被访问),则将数据移到链表头部: 3. 当链表满的时候,将链表尾部的数据丢弃. 1.3. 分析 [命中率] 当存在热点数据时,LRU的效率很好,但偶发性的

【转】缓存淘汰算法系列之1——LRU类

原文地址:http://www.360doc.com/content/13/0805/15/13247663_304901967.shtml 参考地址(一系列关于缓存的,后面几篇也都在这里有):http://www.360doc.com/userhome.aspx?userid=13247663&cid=48# 1. LRU1.1. 原理 LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几

缓存淘汰算法之LRU

1. LRU 1.1. 原理 LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是"如果数据最近被访问过,那么将来被访问的几率也更高". 1.2. 实现 最常见的实现是使用一个链表保存缓存数据,详细算法实现如下: 1. 新数据插入到链表头部: 2. 每当缓存命中(即缓存数据被访问),则将数据移到链表头部: 3. 当链表满的时候,将链表尾部的数据丢弃. 1.3. 分析 [命中率] 当存在热点数据时,LRU的效率很好,但偶发性

LRU缓存算法与pylru

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