作者:shanfeng0828_589 | 来源:互联网 | 2023-05-18 11:15
IamnewinprogrammingingeneralandinJavainparticular.IwanttoimplementanLRUcacheandw
I am new in programming in general and in Java in particular. I want to implement an LRU cache and would like to have O(1) complexity.
我在编程方面是新手,特别是在Java方面。我想实现一个LRU缓存,并希望有O(1)复杂度。
I have seen some implementations in the Internet using a manually implemented doubly linked list for the cache (two arrays, a Node class, previous, next etc.) and a HashMap where Key is the item to be cached and Value is the timestamp.
我已经在Internet上看到了一些实现,使用手动实现的缓存(两个数组,一个节点类,前面的,next等)和一个HashMap,其中键是要缓存的项,值是时间戳。
I really don't see the reason to use timestamps: the inserted item goes to the head of the manually-implemented LinkedList, the evicted item is the cached item located at the tail, and in every insertion the previously cached items are shifted one position towards the tail.
我真的没有看到使用时间戳的理由:插入的条目会进入手动实现的LinkedList的头部,被赶出的项是位于尾部的缓存项,在每次插入之前缓存的项都将一个位置移动到尾部。
The only problems that I see are the following:
我看到的唯一问题是:
For the cache lookup (to find if we have a cache hit or miss for the requested item), we have to "scan" the cache list, which implies a for loop of some type (conventional, for-each etc., I don't really care much at this point). Obviously, we don't want that. I believe this issue can be solved easily by using an array of boolean variables to indicate whether an item is in the cache or not (1: in, 0: out) - let's call it lookupArray - as following: Let's say that the items are distinguished by some numeric ID, i.e. an integer between 1 and N. Then, this lookupArray of booleans will have size N+1 (because array indexing starts from zero) and it will be initialized at all zero values. When the item with numeric ID k, where 1<=k<=N, enters the cache, we set the boolean value at index k of lookupArray to 1. That way, cache lookup does not need any search in the cache: in order to check whether the item with numeric ID k is in the cache or not, we simply check whether the value of lookupArray at index k is 1 or 0, respectively. (We already have the index, i.e. we know where to look, thus there is no need to use a for loop.)
对于缓存查找(如果我们对所请求的项有缓存命中或遗漏),我们必须“扫描”缓存列表,这意味着某个类型的循环(常规的,For -each等),在这一点上我并不十分关心。显然,我们不希望这样。我相信这个问题可以解决很容易通过使用一组布尔变量表明是否一个项目是否在缓存中(1:在0:)——我们称之为lookupArray如下:假设项目的一些数字ID,即一个整数1到N,这lookupArray的布尔值大小N + 1(因为数组索引从0开始),它会在所有零值初始化。当带有数字ID k的项(其中1<=k<=N)进入缓存时,我们在lookupArray的索引k中设置布尔值为1。这样,缓存查找不需要在缓存中进行任何搜索:为了检查带有数字ID k的项是否在缓存中,我们只需要检查索引k中lookupArray的值是否为1或0。(我们已经有了索引,也就是说,我们知道在哪里看,因此没有必要使用for循环。)
The second problem, though, is not easilly solvable. Let's say that we have a cache hit for an item. Then, if this item is not located at the head (i.e. if it is not the most recently used item), we have to locate it in the cache list and then put it at the head. As far as I understand, this implies searching in the cache list, i.e. a for loop. Then, we can't achieve the O(1) objective.
不过,第二个问题并不容易解决。假设我们有一个项目的缓存命中。然后,如果这个项目不是位于头部(也就是说,如果它不是最近使用的项目),我们必须在缓存列表中找到它,然后将它放在头部。据我所知,这意味着在缓存列表中搜索,即for循环。那么,我们就不能实现O(1)目标。
Am I right about (2)? Is any way to do this without using a HashMap and timestamps?
我说的对吗?没有使用HashMap和时间戳的方法可以做到这一点吗?
Due to the fact that I am relatively new in programming as I stated at the beginning of the post, I would really appreciate the use, if possible, of any code snippets demonstrating the implementation with a manually implemented doubly linked list.
由于我在文章开头就已经说过,我在编程方面相对较新的,所以如果可能的话,我会非常感谢使用手工实现的双向链表来演示实现的任何代码片段。
Sorry for the long message, I hope it is not only detailed but also clear.
不好意思,我希望它不仅详细而且清晰。
Thank you!
谢谢你!
1 个解决方案