简易LRU缓存淘汰模拟

Posted zwb1

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简易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 p2
1 p1
-------------------
3 p3
2 p2
1 p1
-------------------
2 p2
3 p3
1 p1
-------------------
4 p4
2 p2
3 p3

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

以上是关于简易LRU缓存淘汰模拟的主要内容,如果未能解决你的问题,请参考以下文章

缓存淘汰策略之LRU

缓存淘汰算法-LRU 实现原理

缓存淘汰算法-LRU 实现原理

缓存淘汰算法-LRU 实现原理

LRU 缓存淘汰算法

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