思路:
LRU Cache:當緩存填滿的時候,刪除最久沒使用過的數據。
通過雙向鏈表記錄數據的使用情況,當get或者put一個<key,value>時,將鏈表中該node移到鏈表頭部。這樣鏈表尾部就是最久沒使用過的node。
通過hash map保存key,value使查詢時間爲O(1),當緩存慢的時候找到鏈表尾部的node並取出key值,刪除map中對應的鍵值對。
Tips:map使用<key,node>的泛型可以通過key直接定位到鏈表中的node,而不需要遍歷鏈表定位key所對應的node。
import java.util.HashMap;
import java.util.Map;
/**
* Created by marsares on 15/7/21.
*/
class Node{
int key;
int value;
Node pre;
Node next;
public Node(int key,int value){
this.key=key;
this.value=value;
}
}
public class LRUCache{
int capacity;
Map<Integer,Node>map;
Node first=null;
Node last=null;
public LRUCache(int capacity) {
map=new HashMap<Integer,Node>();
this.capacity=capacity;
}
public int get(int key) {
if(map.containsKey(key)){
Node node=map.get(key);
remove(node);
addToHead(node);
return node.value;
}else{
return -1;
}
}
public void set(int key, int value) {
if(map.containsKey(key)){
Node node=map.get(key);
remove(node);
Node head=new Node(key,value);
addToHead(head);
map.put(key,head);
}
else if(map.size()<capacity){
Node head=new Node(key,value);
addToHead(head);
map.put(key,head);
}else{
int lastkey=last.key;
remove(last);
map.remove(lastkey);
Node head=new Node(key,value);
addToHead(head);
map.put(key,head);
}
}
private void remove(Node node){
Node p=node.pre;
Node n=node.next;
if(p!=null&&n!=null){
p.next=n;
n.pre=p;
}
else if(p==null&&n!=null){
n.pre=null;
first=n;
}
else if(p!=null&&n==null){
p.next=null;
last=p;
}else{
first=null;
last=null;
}
}
private void addToHead(Node node){
if(first!=null){
node.next=first;
node.pre=null;
first.pre=node;
first=node;
}else{
first=node;
last=node;
node.pre=null;
node.next=null;
}
}
public static void main(String[] args) {
LRUCache lru = new LRUCache(3);
System.out.println(lru.get(2));
lru.set(1, 10);
lru.set(2, 20);
System.out.println(lru.get(1));
lru.set(3, 30);
System.out.println(lru.get(2));
}
}