146. LRU 缓存机制
(1)直接使用LinkedHashMap
package 链表; import java.util.LinkedHashMap; import java.util.Map; public class LRUCache extends LinkedHashMap<Integer, Integer> { private int capacity; public LRUCache(int capacity) { super(capacity, 0.75F, false); this.capacity = capacity; } public int get(int key) { return super.getOrDefault(key, -1); } public void put(int key, int value) { super.put(key, value); } @Override protected boolean removeEldestEntry(Map.Entry eldest) { return size() > capacity; } }
(2)利用hashMap和双向链表实现LRU缓存
package 链表; import java.util.HashMap; public class LRUCache2 { //双向链表存元素顺序 class DeListNode { int key; int val; DeListNode next; DeListNode pre; public DeListNode() { } public DeListNode(int key, int val) { this.key = key; this.val = val; } } private int capacity; private int size = 0; // hashMap存储元素 private HashMap<Integer, DeListNode> map = new HashMap<>(); // 虚拟头尾节点 private DeListNode head; private DeListNode tail; public LRUCache2(int capacity) { this.capacity = capacity; this.head = new DeListNode(); this.tail = new DeListNode(); head.next = tail; tail.pre = head; } // 查询元素,如果不存在返回默认值,存在就把这个元素移动到链表头部 public int get(int key) { if (map.containsKey(key)) { DeListNode deListNode = map.get(key); moveToHead(deListNode); return deListNode.val; } else { return -1; } } // 插入元素,如果元素存在就替换值,并把元素移动到前边,移动到前边就是先删除再重新添加 // 如果元素不存在,就插入元素,并在双向链表头部也插入 // 容量超长了咋办 public void put(int key, int value) { if (map.containsKey(key)) { DeListNode deListNode = map.get(key); deListNode.val = value; moveToHead(deListNode); } else { DeListNode newNode = new DeListNode(key, value); addHead(newNode); map.put(key, newNode); ++size; if (size > capacity) { DeListNode removeNode = removeTail(); map.remove(removeNode.key); --size; } } } private void addHead(DeListNode node) { // 这块也会把新加入的节点和尾节点相连 node.next = head.next; node.pre = head; head.next.pre = node; head.next = node; } private void removeNode(DeListNode node) { DeListNode pre = node.pre; DeListNode next = node.next; pre.next = next; next.pre = pre; } private void moveToHead(DeListNode node) { removeNode(node); addHead(node); } private DeListNode removeTail() { DeListNode preNode = tail.pre; removeNode(preNode); return preNode; } }
。。