使用HashMap+双链表的方式实现。
使用HashMap可以在O(1)的时间查询到缓存key,使用双链表是因为插入的时候要在头部插入,删除最少使用的key需要尾部删除。
import java.util.HashMap;
import java.util.Map;
class LRUCache {
/**
* ["LRUCache","put","put","put","put","get","get","get","get","put","get","get","get","get","get"]
* [[3],[1,1],[2,2],[3,3],[4,4],[4],[3],[2],[1],[5,5],[1],[2],[3],[4],[5]]
* @param args
*/
public static void main(String[] args) {
LRUCache lRUCache = new LRUCache(3);
lRUCache.put(1, 1);
lRUCache.put(2, 2);
lRUCache.put(3, 3);
lRUCache.put(4, 4); // 移除【1,1】
System.out.println(lRUCache.get(4));
System.out.println(lRUCache.get(3));
System.out.println(lRUCache.get(2));
System.out.println(lRUCache.get(1)); //因为被移除了,所以获取不到。
lRUCache.put(5, 5); // 4被移除。
System.out.println(lRUCache.get(1));
System.out.println(lRUCache.get(2));
System.out.println(lRUCache.get(3));
System.out.println(lRUCache.get(4));
System.out.println(lRUCache.get(5));
}
public static void main111(String[] args) {
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
System.out.println(lRUCache.get(1));
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
System.out.println(lRUCache.get(2));
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
System.out.println(lRUCache.get(1));
System.out.println(lRUCache.get(3));
System.out.println(lRUCache.get(4));
}
//为什么需要使用双链表?因为需要移除最少使用那个元素。插入的时候从头部插入,移除的时候从尾部移除。
class Node{
int key; //这里并不能移除,因为已知Node后,还要根据key去删除map中的数据
int value;
Node previous;
Node next;
public Node(int key,int value){
this.key=key;
this.value=value;
}
}
private int capacity;
private Map<Integer,Node> map;
private Node head;
private Node tail;
public LRUCache(int capacity) {
map=new HashMap<>(capacity);
this.capacity=capacity;
this.head=this.tail=null;
}
private void removeNode(){
if(head==tail){
if(tail!=null){
map.remove(tail.key);
}
head=tail=null;
}else{
Node temp=tail;
tail=temp.previous;
temp.previous.next=null;
temp.previous=null;
map.remove(temp.key);
}
}
private void removeNode(Node current){
int tempKey=current.key;
if(current==head){
if(current==tail){
head=tail=null;
}else{
head=current.next;
current.next.previous=null;
current.next=null;
}
}else if(current==tail){
if(head==tail){
head=tail=null;
}else{
tail=current.previous;
current.previous.next=null;
current.previous=null;
}
}else{
current.previous.next=current.next;
current.next.previous=current.previous;
current.next=null;
current.previous=null;
}
map.remove(tempKey);
}
private void insertNode(Node newNode){
if(head==null){
head=tail=newNode;
}else{
newNode.next=head;
head.previous=newNode;
head=newNode;
}
map.put(newNode.key,newNode);
}
private void moveNodeToHead(Node current){
removeNode(current);
insertNode(current);
}
public int get(int key) {
Node current=map.get(key);
if(current!=null){
moveNodeToHead(current);
return current.value;
}
return -1;
}
public void put(int key, int value) {
Node current=map.get(key);
if(current!=null){
current.value=value;
moveNodeToHead(current);
}else{
//删除最少使用的那个node
if(map.size()==capacity){
removeNode();
}
//新增一个node,头插法
Node newNode=new Node(key,value);
insertNode(newNode);
}
}
}