LRU算法的实现

匿名 (未验证) 提交于 2019-12-03 00:11:01

需求

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

  • 初始设计 考虑到性能,可以在内存中创建一个哈希表作为缓存,每当查找一个用户时,会现在哈希表中进行查询,查询不到再去数据库查询。
  • 初始设计存在的问题 随着用户量不断增大,可能会因为哈希表逐渐增大导致内存某一天会被撑爆。
  • 初始设计的优化使用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信息

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