思路:
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));
}
}