LRU算法的实现

和自甴很熟 提交于 2019-11-30 06:29:09

需求

随着公司的业务越来越复杂,需要提供一个用户系统,供各个业务系统来查询用户的基本信息。且业务方对用户信息的查询频率很高,设计的用户系统需要注意性能。

  • 初始设计 考虑到性能,可以在内存中创建一个哈希表作为缓存,每当查找一个用户时,会现在哈希表中进行查询,查询不到再去数据库查询。
  • 初始设计存在的问题 随着用户量不断增大,可能会因为哈希表逐渐增大导致内存某一天会被撑爆。
  • 初始设计的优化使用LRU算法(内存管理算法,Least Recently Used),最近最少使用的思想。算法基于一种假设:长期不被使用的数据,在未来被用到的几率也不大。因此,当数据所占内存达到一定阈值时,我们要移除掉最近最少被使用的数据。

LRU算法

在LRU算法中,使用一种叫作“哈希链表”的数据结构。哈希表由若干个key-value组成,逻辑上这些key-value是无所谓排序的。但在哈希链表中,这些key-value被一个链条串在一起,不再是无序的了,而是有 了固定的排列顺序。每一个key-value都有前驱key-value、后继key-value。所以我们可以把key-value按照最后使用的时间来进行排序。链表的尾部是最近被使用的,头部是最近被使用最少甚至没有被使用过的key-value。所以,当缓存容量达到上限时,会先删除链表最左端的值,再把新的值插入到链表的最右端。

LRU算法实现

注意点: 删除节点的同时,记得把节点的key也要从hashMap中删除

  1 package blogSrc;
  2 
  3 import java.util.HashMap;
  4 
  5 public class LRUCache {
  6     private Node head;
  7     private Node end;
  8 
  9     private HashMap<String,Node> hashMap;
 10     private int limit;  //缓存上限
 11 
 12     public LRUCache(int limit){
 13         this.limit = limit;
 14         this.hashMap = new HashMap<String,Node>();
 15     }
 16 
 17     public void addNode (Node node){
 18         if (head == null){  //空链
 19             head = node;
 20         }
 21 
 22         if(end != null) {  //节点添加到尾部
 23             end.next = node;
 24             node.pre = end;
 25             node.next = null;
 26         }
 27         end = node;
 28     }
 29 
 30     public String  removeNode(Node node){
 31         if(head == end && node == head){  //链表只有一个节点
 32             head = null;
 33             end = null;
 34         }else if (node == end){ //node为最后一个节点
 35             end.pre.next = null;
 36             end = end.pre;
 37         }else if (node == head){  //node为第一个节点
 38             head.next.pre = null;
 39             head = head.next;
 40         }else {  //node为中间节点
 41             node.pre.next = node.next;
 42             node.next.pre = node.pre;
 43         }
 44         return node.key;
 45     }
 46 
 47     //刷新链表
 48     public void refreshNode(Node node){
 49          if (node == end){
 50              return;
 51          }
 52          removeNode(node);  //删除节点
 53          addNode(node); //添加节点
 54     }
 55 
 56     //从链表上取数据
 57     public String get(String key){
 58         Node node = hashMap.get(key);
 59         if (node == null){
 60             return null;
 61         }
 62         refreshNode(node);
 63         return node.value;
 64     }
 65 
 66     //向链表上添加key-value
 67     public void put(String key, String value){
 68         Node node = hashMap.get(key);
 69         if (node == null){
 70             if (hashMap.size() >= limit){
 71                 String oldKey = removeNode(head);  //删除节点
 72                 hashMap.remove(oldKey);  //同时需要把节点的key也从hashmap中删除
 73             }
 74             node = new Node(key,value);
 75             addNode(node);
 76             hashMap.put(key,node);
 77         }else {
 78             node.value = value;
 79             refreshNode(node);
 80         }
 81     }
 82 
 83     //从链表上删除数据
 84     public void remove(String key){
 85         Node node = hashMap.get(key);
 86         if (node == null){
 87             return ;
 88         }
 89         removeNode(node);
 90         hashMap.remove(key);
 91     }
 92 
 93     class Node {
 94         public Node next;
 95         public Node pre;
 96         public String key;
 97         public String value;
 98         Node(String key, String value){
 99             this.key = key;
100             this.value = value;
101         }
102 
103         public String getNextKey() {
104             return next.getKey();
105         }
106 
107         public String getPreKey() {
108             return pre.getKey();
109         }
110 
111         public String getKey() {
112             return key;
113         }
114 
115         public String getValue() {
116             return value;
117         }
118     }
119 
120 
121     public static void main(String[] args){
122         LRUCache lruCache = new LRUCache(10);
123         lruCache.put("001","用户1信息");
124         lruCache.put("002","用户2信息");
125         lruCache.put("003","用户3信息");
126         lruCache.put("004","用户4信息");
127         lruCache.get("003");
128         System.out.println("Now End Node Key is: " + lruCache.end.getKey()+ ",Value is: " +lruCache.end.getValue());
129         lruCache.put("002","用户2信息更新");
130         System.out.println("Now End Node Key is: " + lruCache.end.getKey() + ",Value is: " +lruCache.end.getValue() );
131         lruCache.put("006","用户6信息");
132         System.out.println("Now End Node Key is: " + lruCache.end.getKey()+ ",Value is: " +lruCache.end.getValue());
133     }
134 
135 }

 

结果:

Now End Node Key is: 003,Value is: 用户3信息
Now End Node Key is: 002,Value is: 用户2信息更新
Now End Node Key is: 006,Value is: 用户6信息

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!