运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。
获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。
写入数据 put(key, value) - 如果密钥不存在,则写入其数据值。如果密钥存在,则更新其数据值。当缓存容量达到上限时,它应该在写入新数据之前删除最近最少使用的数据值,从而为新的数据值留出空间。
你是否可以在 O(1) 时间复杂度内完成这两种操作?
import java.util.HashMap;
public class LRU {
public static class Node<K, V>{
public K key;
public V value;
public Node<K, V> last;
public Node<K, V> next;
public Node(K key, V value){
this.key = key;
this.value = value;
}
}
public static class NodeDoubleLinkedList<K, V>{
private Node<K, V> head;
private Node<K, V> tail;
public NodeDoubleLinkedList(){
this.head = null;
this.tail = null;
}
public void addNode(Node<K, V> newNode){
if (newNode == null) {
return;
}
if (this.head == null){
this.head = newNode;
this.tail = newNode;
}else {
this.tail.next = newNode;
newNode.last = this.tail;
this.tail = newNode;
}
}
public void moveToTail(Node<K, V> node){
if (this.tail == node){
return;
}
if (node == this.head){
this.head = node.next;
this.head.last = null;
}else{
node.last.next = node.next;
node.next.last = node.last;
}
node.next = null;
node.last = this.tail;
this.tail.next = node;
this.tail = node;
}
public Node<K, V> removeHead(){
if (this.head == null){
return null;
}
Node<K, V> res = this.head;
if (this.head == this.tail) {
this.head = null;
this.tail= null;
}else {
this.head = res.next;
res.next = null;
this.head.last = null;
}
return res;
}
}
public static class MyCache<K, V>{
private HashMap<K, Node<K, V>> keyNodeMap;
private NodeDoubleLinkedList<K, V> nodeList;
private int capacity;
public MyCache(int capacity){
if (capacity < 1){
throw new RuntimeException("should more than 0");
}
this.capacity = capacity;
this.keyNodeMap = new HashMap<K, Node<K, V>>();
this.nodeList = new NodeDoubleLinkedList<K, V>();
}
public V get(K key){
if (keyNodeMap.containsKey(key)){
Node<K, V> res = keyNodeMap.get(key);
this.nodeList.moveToTail(res);
return res.value;
}
return null;
}
public void set(K key, V value) {
if (this.keyNodeMap.containsKey(key)){
Node<K, V> res = this.keyNodeMap.get(key);
res.value = value;
this.nodeList.moveToTail(res);
}else{
Node<K, V> newNode = new Node<K, V>(key, value);
this.keyNodeMap.put(key, newNode);
this.nodeList.addNode(newNode);
if (this.keyNodeMap.size() == this.capacity + 1){
removeMostUnUsedCache();
}
}
}
public void removeMostUnUsedCache(){
Node<K, V> head = this.nodeList.removeHead();
K key = head.key;
this.keyNodeMap.remove(key);
}
}
public static void main(String[] args) {
MyCache<String, Integer> testCache = new MyCache<>(3);
testCache.set("a", 1);
System.out.println(testCache.get("a"));
}
}