题目:
思路:
1 运用 LinkedHashMap 已经实现好的LRU
继承 LinkedHashMap 重写 removeEldestEntry 方法 当size() > capatity 返回true
2 使用HashMap 和 双向链表
读缓存时从HashMap 中查找key,更新缓存时同时更新HashMap和双向链表,双向链表始终按照访问顺序排列
(一)代码 使用LinkedHashMap
public class LRUCache extends LinkedHashMap<Integer,Integer>{ //容量 private int capacity; public LRUCache(int capacity) { super(capacity,0.75F,true); 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; } }
(二)使用HashMap 和 双向链表
public class LRUCache { //缓存容量 private final int capacity; //用于加速缓存项随机访问性能的hashmap private HashMap<Integer, Entry> map; //双向链表头结点 private Entry head; //双向链表尾节点 private Entry tail; public LRUCache(int capacity) { this.capacity = capacity; head = new Entry(0,0); tail = new Entry(0,0); head.next = tail; tail.prev = head; map = new HashMap<Integer,Entry>(); } public int get(int key){ //如果是已经存在的,更新值到末端,移除是从头进行移除(相当于放到了最新的位置) if(map.containsKey(key)){ Entry entry = map.get(key); popToTail(entry); return entry.value; } return -1; } public void put(int key,int value){ //如果key存在,就更新value if(map.containsKey(key)){ Entry entry = map.get(key); entry.value = value; }else{ Entry entry = new Entry(key,value); if(map.size() > capacity){ Entry first = removeFirst(); map.remove(first.key); } addToTail(entry); map.put(key,entry); } } class Entry{ int key, int value, Entry prev, Entry next, Entry(int key,int value){ this.key = key; this.value = value; } } //移除链表首端节点 private Entry removeFirst(){ Entry first = head.next; Entry second = first.next; head.next = second; second.prev = head; return first; } //添加 entry 节点到链表末端 private void addToTail(Entry entry){ Entry last = tail.prev; last.next = entry; tail.prev = entry; entry.prev = last; entry.next = tail; } //将entry 节点移动到链表末端 private void popToTail(Entry entry){ //1 删除 entry 当前位置信息 Entry prev = entry.prev; //entry 的前指针 Entry next = entry.next; //entry 的后指针 //让前指针 指向 后指针 , 后指针指向前指针,从而达到删除的目的 prev.next = next; next.prev = prev; //2 添加到末尾的位置 Entry last = tail.prev; last.next = entry; //插入点的前节点的 next 指针指向entry tail.prev = entry; //插入点的后节点的 prev 指针指向entry entry.prev = last; //更新entry 的前指针 entry.next = tail; //更新entry 的后指针 } }
今晚吃凉皮