基于 LinkedHashMap 的 LRU 算法实现
public class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V> {private final int maxCapacity;private static final float DEFAULT_LOAD_FACTOR = 0.75f;private final ReadWriteLock rwLock = new ReentrantReadWriteLock();private final Lock rLock = rwLock.readLock();private final Lock wLock = rwLock.writeLock();public LRULinkedHashMap(int maxCapacity) {super(maxCapacity, DEFAULT_LOAD_FACTOR, true);this.maxCapacity = maxCapacity;}/** LRU 核心 */@Overrideprotected boolean removeEldestEntry(Map.Entry<K, V> eldest) {rLock.lock();try {return size() > maxCapacity;} finally {rLock.unlock();}}@Overridepublic boolean containsKey(Object key) {rLock.lock();try {return super.containsKey(key);} finally {rLock.unlock();}}@Overridepublic V get(Object key) {rLock.lock();try {return super.get(key);} finally {rLock.unlock();}}@Overridepublic V put(K key, V value) {wLock.lock();try {return super.put(key, value);} finally {wLock.unlock();}}@Overridepublic int size() {rLock.lock();try {return super.size();} finally {rLock.unlock();}}@Overridepublic void clear() {rLock.lock();try {super.clear();} finally {rLock.unlock();}}public ArrayList<Map.Entry<K, V>> getAll() {rLock.lock();try {return new ArrayList<>(super.entrySet());} finally {rLock.unlock();}}}
class LruCache<T> implements Serializable {private static final long serialVersionUID = 1L;// Although the internal implementation uses a Map, this cache// implementation is only concerned with the keys.private final Map<T,T> cache;public LruCache(final int cacheSize) {cache = new LinkedHashMap<T,T>() {private static final long serialVersionUID = 1L;@Overrideprotected boolean removeEldestEntry(Map.Entry<T,T> eldest) {if (size() > cacheSize) {return true;}return false;}};}public void add(T key) {synchronized (cache) {cache.put(key, null);}}public boolean contains(T key) {synchronized (cache) {return cache.containsKey(key);}}}
基于双向链表的 LRU 算法实现
public class LRUCache<K, V> {class CacheNode {K key;V value;CacheNode prev;CacheNode next;}private final int maxCapacity;private final Hashtable<K, CacheNode> nodes;private int curSize;private CacheNode head;private CacheNode tail;public LRUCache(int maxCapacity) {this.maxCapacity = maxCapacity;nodes = new Hashtable<>(maxCapacity);}/*** 新增缓存** @param k 缓存key* @param v 缓存value*/public void put(K k, V v) {CacheNode node = nodes.get(k);if (Objects.isNull(node)) {if (curSize >= maxCapacity) {if (Objects.nonNull(tail)) {nodes.remove(tail.key);}removeLast();}node = new CacheNode();}node.key = k;node.value = v;move2Head(node);curSize++;}/*** 获取缓存*/public V get(K k) {if (Objects.isNull(k)) {return null;}final CacheNode node = nodes.get(k);if (Objects.isNull(node)) {return null;}move2Head(node);return node.value;}/*** 将缓存删除** @param key 缓存节点 key*/public V remove(K key) {if (key == null) {return null;}final CacheNode node = nodes.get(key);if (node != null) {if (node.prev != null) {node.prev.next = node.next;}if (node.next != null) {node.next.prev = node.prev;}if (head == node) {head = node.next;}if (tail == node) {tail = node.prev;}}curSize--;return node == null ? null : node.value;}/*** 清空容器*/public void clear() {nodes.clear();curSize = 0;head = null;tail = null;}/*** 移动到链表头, 表示该节点最新使用过** @param node 节点*/private void move2Head(CacheNode node) {if (node == null || node == head) {return;}if (node.prev != null) {node.prev.next = node.next;}if (node.next != null) {node.next.prev = node.prev;}if (head != null) {node.next = head;head.prev = node;}head = node;node.prev = null;if (tail == null) {tail = head;}}/*** 删除链表最后一个节点, 表示最近最少使用的缓存*/private void removeLast() {if (tail != null) {if (tail.prev != null) {tail.prev.next = null;} else {head = null;}tail = tail.prev;}}}
参考:
