Java单链表实现LRU内存缓存淘汰算法

一、什么是LRU

  在了解什么是LRU算法时,得先清楚软件有哪些缓存,软件缓存分为:

  1、内存缓存;

  2、数据库缓存;

  3、网络缓存;

  速度依次减慢,缓存到内存中的数据,长时间可能会有一些无用的数据占用内存甚至导致内存雪崩的发生,为了解决这些,产生了LRU(Least Recently Used)算法。LRU算法只是解决问题的其中一种,还有包括FIFO(First In, First Out),LFU(Least Frequently Used)算法。这里我们只讲LRU算法的实现。

二、LRU算法内容

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

  2、当缓存命中(即缓存数据被访问),数据要移到表头;

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

二、LRU算法实现

   根据描述,我们采用单链表的形式来实现该需求:

  (1)先实现单链表

  1 //单链表
  2 public class LinkedList<T> {
  3     
  4     Node list; //链表的头节点
  5     int size; //链表有多少个节点
  6     
  7     public LinkedList() {
  8         size = 0;
  9     }
 10     
 11     //添加节点
 12     //在头部添加节点
 13     public void put(T data) {
 14         Node head = list;
 15         Node curNode = new Node(data, list); //构建新节点,同时将该节点的下一个节点指向list
 16         list = curNode; //更新头节点为新节点
 17         size++;
 18     }
 19     
 20     //在链表的index 位置插入一个新的数据data
 21     public void put(int index,T data) {
 22         checkPositionIndex(index);
 23         Node cur = list;
 24         Node head = list;
 25         for(int i = 0; i < index; i++) {
 26             head = cur;
 27             cur = cur.next;
 28         }
 29         Node node = new Node(data, cur); //构建新节点,下一个节点指向原来的index节点
 30         head.next = node; //将index-1节点的下一个节点指向新构建的节点
 31         size++;
 32 
 33     }
 34 
 35     //删除节点
 36     //删除头部节点
 37     public T remove() {
 38         if (list != null) {
 39             Node node = list; //获取头节点
 40             list = list.next; //将头节点指向原本头节点的下一个节点
 41             node.next = null; // GC 回收   将原本的头节点的下一个节点指向设为null
 42             size--;
 43             return node.data;
 44         }
 45         return null;
 46     }
 47     
 48     public T remove(int index) { //删除指定下标位置的节点
 49         checkPositionIndex(index);
 50         Node head = list;
 51         Node cur = list;
 52         for(int i = 0; i < index; i++) {
 53             head = cur;
 54             cur = cur.next;
 55         }
 56         head.next = cur.next;
 57         cur.next = null;//GC
 58         size--;
 59         return cur.data;
 60     }
 61     
 62     public T removeLast() { //删除最后一个节点
 63         if (list != null) {
 64             Node node = list;
 65             Node cur = list;
 66             while(cur.next != null) {
 67                 node = cur;
 68                 cur = cur.next;
 69             }
 70             node.next = null;
 71             size--;
 72             return cur.data;
 73             
 74         }
 75         return null;
 76     }
 77     //修改index位置的节点数据
 78     public void set(int index,T newData) {
 79         checkPositionIndex(index);
 80         Node head = list;
 81         for(int i = 0; i < index; i++) {
 82             head = head.next;
 83         }
 84         head.data = newData;
 85     }
 86     
 87     //查询节点
 88     //get 头部节点
 89     public T get() {
 90         Node node = list;
 91         if (node != null) {
 92             return node.data;
 93         } else {
 94             return null;
 95         }
 96     }
 97     
 98     public T get(int index) { //获取下标index处的节点
 99         checkPositionIndex(index);
100         Node node = list;
101         for(int i = 0; i < index; i++) {
102             node = node.next;
103         }
104         return node.data;
105     }
106     
107     //检测index是否在链表范围以内
108     public void checkPositionIndex(int index) {
109         if(!(index >=0 && index <=size)) {
110             throw new IndexOutOfBoundsException("index: " + index + ", size: " + size);
111         }
112         
113     }    
114     
115     //节点的信息
116     class Node {
117         T data;
118         Node next;
119         
120         public Node(T data,Node node) {
121             this.data = data;
122             this.next = node;
123         }
124     }
125 }

   (2)实现LRU缓存回收算法

 1 public class LruLinkedList<T> extends LinkedList<T> {
 2     
 3     int memory_size; // 用于限定内存空间大小,也就是缓存的大小,这里模拟大小
 4     static final int DEFAULT_CAP = 5; //默认5个大小
 5     
 6     public LruLinkedList() {
 7         this(DEFAULT_CAP);
 8     }
 9     
10     public LruLinkedList(int default_memory_size) {
11         memory_size = default_memory_size;
12     }
13     
14     //LRU添加节点
15     public void lruPut(T data) {
16         if (size >= memory_size) {
17             removeLast();
18             put(data);
19         } else {
20             put(data);
21         }
22     }
23     
24     //LRU删除
25     public T lruRemove(){
26         return removeLast();
27     }
28     
29     //LRU访问
30     public T lruGet(int index) {
31         checkPositionIndex(index);
32         Node node = list;
33         Node pre = list;
34         for(int i = 0; i < index; i++) {
35             pre = node;
36             node = node.next;
37         }
38         T resultData = node.data;
39         //将访问的节点移到表头
40         pre.next = node.next;
41         Node head = list;
42         node.next = head;
43         list = node;
44         return resultData;
45     }
46 
47     public static void main(String[] args) {
48         LruLinkedList<Integer> lruLinkedList = new LruLinkedList<>(5);
49         for(int i = 0; i <4; i++) {
50             lruLinkedList.lruPut(i);
51         }
52         lruLinkedList.lruGet(2)
53         lruLinkedList.lruPut(12);
54         lruLinkedList.lruPut(76);
55     }
56 }

  到这里整个LRU算法就算模拟完成。

 

posted @ 2020-11-30 23:39  bug_easy  阅读(277)  评论(0编辑  收藏  举报