赞
踩
编程模拟实现利用LRU(最近最久未使用)替换算法的缓存.
LRU算法: 即最近最久未使用算法.
假设最上方为最近使用的元素:
3 4 5
4 -> get(4) -> 3 -> set(5) -> 4
2 2 3
数据结构选取HashMap, 双链表.
HashMap: 记录 键值对:<key, Node<key, value>>.
链表: 记录Node<key, value>
这里使用HashMap, 可以将查找的时间复杂度降低为O(1).
package cn.geek51.nowcoder.class01; /** * 最近最久未使用算法(LRU)实现 * HashMap + 双向链表 */ import java.util.ArrayList; import java.util.HashMap; import java.util.List; class Node<K, V> { public Node<K, V> last; public Node<K, V> next; public K key; public V value; public Node(K key, V value) { this.key = key; this.value = value; this.last = null; this.next = null; } @Override public String toString() { return "key:" + this.key + " value:" + this.value; } } class MyCache<K, V> { private int capacity = 0; private HashMap<K, Node<K, V>> keyNodeMap; private NodeDoubleLinkedList<K, V> nodeList; public MyCache(int capacity) { this.nodeList = new NodeDoubleLinkedList<>(); this.keyNodeMap = new HashMap<>(); this.capacity = capacity; } // 获取缓存中元素值 public V get(K key) { if (this.keyNodeMap.containsKey(key)) { Node<K, V> node = this.keyNodeMap.get(key); this.nodeList.moveToLastNode(node); return node.value; } else { return null; } } public void set(K key, V value) { if (this.keyNodeMap.containsKey(key)) { // 缓存中已经存在 Node<K, V> node = this.keyNodeMap.get(key); node.value = value; this.nodeList.moveToLastNode(node); } else { Node<K, V> newNode = new Node<>(key, value); this.keyNodeMap.put(key, newNode); this.nodeList.addNode(newNode); // 考虑替换 if (this.keyNodeMap.size() == capacity + 1) { Node<K, V> removeNode = this.nodeList.removeHead(); this.keyNodeMap.remove(removeNode.key); } } } // 删除缓存元素 public Node<K, V> del(K key) { if (key == null) return null; if (this.keyNodeMap.containsKey(key)) { Node<K, V> removeNode = this.keyNodeMap.get(key); this.keyNodeMap.remove(key); this.nodeList.deleteNode(removeNode); return removeNode; } else { return null; } } // 获取所有节点的数组 public List<Node<K, V>> all() { return this.nodeList.getAllNode(); } } class NodeDoubleLinkedList<K, V> { public Node<K, V> head; public Node<K, V> tail; public NodeDoubleLinkedList() { this.head = null; this.tail = null; } public void addNode(Node<K, V> newNode) { if (newNode == null) return; // 链表中无节点 if (this.head == null) { this.head = newNode; this.tail = newNode; } else { // 链表中有节点, 添加到尾部 this.tail.next = newNode; newNode.last = this.tail; newNode.next = null; this.tail = newNode; } } // 删除指定节点 public void deleteNode(Node<K, V> removeNode) { if (removeNode == null) return; if (head == removeNode) { // 如果是头节点 this.head = removeNode.next; head.last = null; } else if (tail == removeNode) { // 如果是尾节点 this.tail = this.tail.last; this.tail.next = null; removeNode.last = null; removeNode.next = null; } else { removeNode.last.next = removeNode.next; removeNode.next.last = removeNode.last; removeNode.last = null; removeNode.next = null; } } // 移动元素到链表尾部, 操作已经存在缓存中的元素时触发 public void moveToLastNode(Node<K, V> node) { if (this.tail == node) return; // 原来是头部元素 // 先断开与原链表的连接 if (this.head == node) { this.head = this.head.next; this.head.last = null; } else { node.last.next = node.next; node.next.last = node.last; } this.tail.next = node; node.last = tail; tail = node; } // 删除 public Node<K, V> removeHead() { // 链表为空 if (this.head == null) return null; // 获取头部元素 Node<K, V> res = head; if (this.head == this.tail) { this.head = null; this.tail = null; } else { // 多于1个元素 this.head = res.next; res.next = null; this.head.last = null; } return res; } // 获取所有元素 public List<Node<K, V>> getAllNode() { List<Node<K, V>> list = new ArrayList<>(); Node<K, V> t = tail; while (t != null) { list.add(t); t = t.last; } return list; } } public class LeastRecentlyUsedCache { public static void main(String[] args) { MyCache<String, Integer> cache = new MyCache<>(3); cache.set("A", 3); cache.set("B", 4); cache.set("C", 5); cache.set("D", 5); cache.set("B", 2); cache.set("C", 5); cache.del("C"); cache.set("A", 5); List<Node<String, Integer>> nodeList = cache.all(); for (Node node : nodeList) { System.out.println(node); } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。