LRU演算法的實現
阿新 • • 發佈:2020-11-20
緣由:看到redis的快取淘汰機制,便自己實現了一下
程式碼實現(雙向連結串列+HashMap)
package com.jarjune.jdalao.framework.algorithm; import java.util.*; /** * LRU * @author jarjune * @version 1.0.1 * @date 2020/11/19 */ public class LRUCache<K, V> { // 快取Node private Map<K, Node<K, V>> cache; // 雙向連結串列首結點 private Node<K, V> first; // 雙向連結串列尾結點 private Node<K, V> last; // 最大快取容量 private int capacity; public LRUCache(int capacity) throws Exception { if(capacity < 2) { throw new Exception("capacity小於2就沒啥意義了..."); } this.cache = new HashMap<>((int) (capacity / 0.75f + 1)); this.capacity = capacity; } private class Node<K, V> { K k; V v; Node<K, V> prev; Node<K, V> next; Node(K k, V v) { this.k = k; this.v = v; } @Override public String toString() { return "Node{" + "k=" + k + ", v=" + v + '}'; } } public int size() { return cache.size(); } public void put(K k, V v) { Node<K, V> node = cache.get(k); if(null == node) { node = new Node<>(k, v); // 大於等於capacity容量最大值時 if(cache.size() >= capacity) { if(null != last) { // 移除最後一個元素的快取 cache.remove(last.k); last = last.prev; if(null == last) { first = null; } else { last.next = null; } } } cache.put(k, node); } else { node.v = v; } moveToFirst(node); } /** * 1(first) * ↑ ↓ * 2(node) * ↑ ↓ * 3 * ↑ ↓ * 4(last) */ private void moveToFirst(Node<K, V> node) { if(first == null || last == null) { first = last = node; return; } // 如果是頭結點就結束 if(node == first) { return; } // 如果是尾結點,尾結點就等於當前結點的上一個結點 if(node == last) { last = node.prev; } if(null != node.next) { node.next.prev = node.prev; } if(null != node.prev) { node.prev.next = node.next; } node.next = first; first.prev = node; node.prev = null; first = node; } class LRUIterable implements Iterable<Node<K, V>> { @Override public Iterator<Node<K, V>> iterator() { return new Iterator<Node<K, V>>() { private Node<K, V> node = first; @Override public boolean hasNext() { return node != null; } @Override public Node<K, V> next() { Node<K, V> tmp = node; node = node.next; return tmp; } }; } } public Iterator<Node<K, V>> iterator() { return new LRUIterable().iterator(); } public Set<K> keySet() { Iterator<Node<K, V>> iterator = iterator(); Set<K> keys = new LinkedHashSet<>(); while(iterator.hasNext()) { keys.add(iterator.next().k); } return keys; } @Override public String toString() { StringBuilder sb = new StringBuilder(); for (Node<K, V> node: new LRUIterable()) { sb.append(node); } return sb.toString(); } }
搞定