java 中map get() 时间复杂度为o(1),Java中具有泛型和O(1)操作的LRU缓存

本文介绍了如何使用HashMap和双向链表来实现一个高效的LRU(最近最少使用)缓存机制。通过这种数据结构,可以在O(1)的时间复杂度内完成查询和更新操作。在get()方法中,找到的项会移动到链表的最右侧,而在put()方法中,当缓存满时,会删除链表最左侧的项,同时更新HashMap。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

小编典典

从问题本身可以看出,查询链接列表时会出现O(n)操作问题。因此,我们需要替代的数据结构。我们需要能够从HashMap更新项目的上次访问时间,而无需进行搜索。

我们可以保留两个单独的数据结构。 具有(Key,Pointer) 对和 双链表 的 HashMap

将用作删除和存储值的优先级队列。从HashMap,我们可以指向双向链表中的元素并更新其检索时间。因为我们直接从HashMap转到列表中的项目,所以我们的时间复杂度保持在O(1)

例如,我们的双向链表如下所示:

least_recently_used -> A B C D E

我们需要保持指向LRU和MRU项目的指针。条目的值将存储在列表中,当我们查询HashMap时,我们将获得一个指向列表的指针。在get()上,我们需要将该项目放在列表的最右侧。在put(key,value)上,如果缓存已满,则需要从列表和HashMap中删除列表最左侧的项目。

以下是Java中的示例实现:

public class LRUCache{

// Define Node with pointers to the previous and next items and a key, value pair

class Node {

Node previous;

Node next;

T key;

U value;

public Node(Node previous, Node next, T key, U value){

this.previous = previous;

this.next = next;

this.key = key;

this.value = value;

}

}

private HashMap> cache;

private Node leastRecentlyUsed;

private Node mostRecentlyUsed;

private int maxSize;

private int currentSize;

public LRUCache(int maxSize){

this.maxSize = maxSize;

this.currentSize = 0;

leastRecentlyUsed = new Node(null, null, null, null);

mostRecentlyUsed = leastRecentlyUsed;

cache = new HashMap>();

}

public V get(K key){

Node tempNode = cache.get(key);

if (tempNode == null){

return null;

}

// If MRU leave the list as it is

else if (tempNode.key == mostRecentlyUsed.key){

return mostRecentlyUsed.value;

}

// Get the next and previous nodes

Node nextNode = tempNode.next;

Node previousNode = tempNode.previous;

// If at the left-most, we update LRU

if (tempNode.key == leastRecentlyUsed.key){

nextNode.previous = null;

leastRecentlyUsed = nextNode;

}

// If we are in the middle, we need to update the items before and after our item

else if (tempNode.key != mostRecentlyUsed.key){

previousNode.next = nextNode;

nextNode.previous = previousNode;

}

// Finally move our item to the MRU

tempNode.previous = mostRecentlyUsed;

mostRecentlyUsed.next = tempNode;

mostRecentlyUsed = tempNode;

mostRecentlyUsed.next = null;

return tempNode.value;

}

public void put(K key, V value){

if (cache.containsKey(key)){

return;

}

// Put the new node at the right-most end of the linked-list

Node myNode = new Node(mostRecentlyUsed, null, key, value);

mostRecentlyUsed.next = myNode;

cache.put(key, myNode);

mostRecentlyUsed = myNode;

// Delete the left-most entry and update the LRU pointer

if (currentSize == maxSize){

cache.remove(leastRecentlyUsed.key);

leastRecentlyUsed = leastRecentlyUsed.next;

leastRecentlyUsed.previous = null;

}

// Update cache size, for the first added entry update the LRU pointer

else if (currentSize < maxSize){

if (currentSize == 0){

leastRecentlyUsed = myNode;

}

currentSize++;

}

}

}

2020-09-18

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值