# LRU Cache的实现

LeetCode 146 LRU Cache

## 1. 题目描述

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set.

get(key) – Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
set(key, value) – Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

## 2. 基于HashMap实现

1. 新加入的Node插入链表头
2. 访问（取或更新）了已存在Node，则将该Node移到链表头
3. 若Map的size大于Cache容量，则删除链表尾节点

``````public class LRUCache {

private class Node {
int key;
int value;
Node prev; // 上一个被访问的节点
Node next; // 下一个被访问的节点

public Node(int key, int value) {
this.key = key;
this.value = value;
prev = null;
next = null;
}
}

private Map<Integer, Node> cache = new HashMap<>();
private int capacity;
private Node head = new Node(-1, -1);
private Node tail = new Node(-1, -1);

public LRUCache(int capacity) {
this.capacity = capacity;
}

public int get(int key) {
Node node = cache.get(key);
if (node == null)
return -1;

// 访问了该节点，所以将节点移到链表尾
moveToTail(node);
return node.value;
}

public void set(int key, int value) {
Node node = cache.get(key);
if (node != null) {
node.value = value;
// 更新了该节点，所以将节点移到链表尾
moveToTail(node);
return;
}

if (cache.size() == capacity) {
}
Node insert = new Node(key, value);
cache.put(key, insert);

// 新插入了节点，将该节点添加到链表尾
}

private void moveToTail(Node node) {
// remove node
node.prev.next = node.next;
node.next.prev = node.prev;
node.prev = tail.prev;
node.next = tail;
node.prev.next = node;
tail.prev = node;
}

node.prev = tail.prev;
node.next = tail;
node.prev.next = node;
tail.prev = node;
}
}``````

``````public class LRUCache<K, V> extends LinkedHashMap<K, V> {

private static final long serialVersionUID = 1L;
// 缓存的容量
private int capacity;

LRUCache(int capacity){
// 初始容量initialCapacity = 16
// accessOrder = true，表示按访问顺序迭代
super(16, 0.75f, true);
this.capacity=capacity;
}

/** * removeEldestEntry方法用于判断是否该删除最老元素（进入map最久或最久未被访问的元素） * 在LinkedHashMap中，该方法放回false，相当于条件一直不满足，不会删除最老元素 * 当Map为Cache时，该方法非常有用，当map.size() > capacity时，删除最久未被访问的元素 */
@Override
public boolean removeEldestEntry(Map.Entry<K, V> eldest){
return size() > capacity;
}
}``````

## 4. Android LruCache

``````public class LruCache<K, V> {
...

public final V get(K key) {
if (key == null) {
throw new NullPointerException("key == null");
}

V mapValue;
synchronized (this) {
mapValue = map.get(key);
if (mapValue != null) {
hitCount++;
return mapValue;
}
missCount++;
}
...
}

public final V put(K key, V value) {
if (key == null || value == null) {
throw new NullPointerException("key == null || value == null");
}

V previous;
synchronized (this) {
putCount++;
size += safeSizeOf(key, value);
previous = map.put(key, value);
if (previous != null) {
size -= safeSizeOf(key, previous);
}
}
...
}

public synchronized final int size() {
return size;
}
}``````