运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制 。
实现 LRUCache 类:
LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存
int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
解答:
方法1:使用额外的list作为辅助
public class LRUCache { private int capacity; private Map<Integer, Integer> map; private List<Integer> list; public LRUCache(int capacity) { this.capacity = capacity; map = new HashMap<Integer, Integer>(); list = new LinkedList<Integer>(); } public int get(int key) { if (map.containsKey(key)) { int pos = list.indexOf(key); list.remove(pos); list.add(key); return map.get(key); } return -1; } public void put(int key, int value) { if (map.containsKey(key)) { int pos = list.indexOf(key); list.remove(pos); list.add(key); map.put(key, value); } else { if (map.size() == capacity) { int removeKey = list.get(0); list.remove(0); map.remove(removeKey); } map.put(key, value); list.add(key); } } }
方法2:利用LinkedHashMap的插入序(默认)
public class LRUCache1 { private int capacity; private LinkedHashMap<Integer, Integer> map; public LRUCache1(int capacity) { this.capacity = capacity; map = new LinkedHashMap<>(); } public int get(int key) { if (map.containsKey(key)) { int value = map.get(key); map.remove(key); map.put(key, value); // 先删后加,保证最新 return value; } return -1; } public void put(int key, int value) { if (map.containsKey(key)) { map.remove(key); map.put(key, value); } else { if (map.size() == capacity) { // 删除第一个元素, 即head的下一个(head是空) Iterator<Map.Entry<Integer, Integer>> iterator = map.entrySet().iterator(); iterator.next(); iterator.remove(); } map.put(key, value); } } }
方法3:利用LinkedHashMap的访问序(非默认,构造函数中进行设置)
public class LRUCache2 { private LinkedHashMap<Integer, Integer> map; public LRUCache2(int capacity) { // accessOrder:false--基于插入顺序(默认) true--基于访问顺序 map = new LinkedHashMap<Integer, Integer>(0, 0.75f, true) { private static final long serialVersionUID = 1L; @Override protected boolean removeEldestEntry(Map.Entry<Integer, Integer> arg0) { // TODO Auto-generated method stub return size() > capacity; // 当put进新的值方法返回true时,便移除该map中最老的键和值 } }; } public int get(int key) { return map.getOrDefault(key, -1); } public void put(int key, int value) { map.put(key, value); } }