Least Frequently Used 😆
简单原理和实现参考: 漫画:什么是LRU算法
简单版本
可以使用JDK自带的LinkedHashMap
数据结构来实现
方法说明
//LinkedHashMap的一个构造函数,当参数accessOrder为true时,即会按照访问顺序排序,最近访问的放在最前,最早访问的放在后面 public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) { super(initialCapacity, loadFactor); this.accessOrder = accessOrder; } //LinkedHashMap自带的判断是否删除最老的元素方法,默认返回false,即不删除老数据 //我们要做的就是重写这个方法,当满足一定条件时删除老数据 protected boolean removeEldestEntry(Map.Entry<K,V> eldest) { return false; }
实现方式
final int cacheSize = 100; Map<String, String> map = new LinkedHashMap<String, String>((int) Math.ceil(cacheSize / 0.75f) + 1, 0.75f, true) { @Override protected boolean removeEldestEntry(Map.Entry<String, String> eldest) { return size() > cacheSize; } };
手写版本
/** * LRU缓存实现 * * @author Miguel.hou * @version v1.0 * @date 2019-11-22 */ public class LRUCache<V> { private Node<V> head; private Node<V> tail; private HashMap<String, Node<V>> hashMap; private Integer capacity; public LRUCache(Integer capacity) { if (capacity <= 0) { throw new IllegalArgumentException("capacity must greater than 0"); } this.capacity = capacity; hashMap = new HashMap<>(); } public synchronized V get(String key) { Node<V> node = hashMap.get(key); if (node == null) { return null; } // 刷新节点 refreshNode(node); return node.value; } public synchronized void put(String key, V value) { Node<V> node = hashMap.get(key); if (node == null) { // 判断是否大于容量,需要去除首节点 if (hashMap.size() >= capacity) { String rmKey = removeNode(head); hashMap.remove(rmKey); } // 加入队列 Node<V> newNode = new Node<>(key, value); addNode(newNode); hashMap.put(key, newNode); } else { // node存在,刷新值 node.value = value; refreshNode(node); } } public synchronized void remove(String key) { Node<V> node = hashMap.get(key); if (node == null) { return; } removeNode(node); hashMap.remove(key); } /** * 刷新节点位置 * @param node */ private void refreshNode(Node<V> node) { if (node == tail) { // 尾节点,不需要更新节点 return; } // 删除节点 removeNode(node); // 新增节点 addNode(node); } private void addNode(Node<V> node) { if (tail != null) { tail.next = node; node.pre = tail; node.next = null; } tail = node; if (head == null) { head = node; } } private String removeNode(Node<V> node) { if (node == tail) { tail = node.pre; } else if (node == head) { head = node.next; } else { node.pre.next = node.next; node.next.pre = node.pre; } return node.key; } class Node<V> { public Node(String key, V value) { this.key = key; this.value = value; } Node<V> pre; Node<V> next; String key; V value; } public static void main(String[] args) { LRUCache<String> lruCache = new LRUCache<>(3); lruCache.put("001", "用户1信息"); lruCache.put("002", "用户2信息"); lruCache.put("003", "用户3信息"); lruCache.put("004", "用户4信息"); lruCache.put("005", "用户5信息"); System.out.println(lruCache.get("004")); System.out.println(lruCache.get("003")); System.out.println(123); } }