JavaScript怎么实现LRU缓存淘汰算法

其他教程   发布日期:2025年04月19日   浏览次数:146

这篇文章主要讲解了“JavaScript怎么实现LRU缓存淘汰算法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript怎么实现LRU缓存淘汰算法”吧!

如何实现LRU缓存淘汰算法?

LRU(Least Recently Used)缓存淘汰算法是一种常见的缓存淘汰策略,它的核心思想是优先淘汰最近最少使用的缓存数据,以保证缓存中的数据始终是最热门的。

使用哈希表和双向链表

LRU缓存淘汰算法的核心在于如何快速定位最近最少使用的缓存数据,这可以通过哈希表和双向链表的结合来实现。具体来说,我们可以使用一个哈希表来存储缓存数据的键值对,同时使用一个双向链表来维护缓存数据的访问顺序,每次访问缓存时,我们将访问的数据节点移动到链表头,当缓存满时,淘汰链表尾部的节点即可。

哈希表实现LRU缓存淘汰算法

下面是一个使用哈希表实现LRU缓存淘汰算法的例子,假设我们要实现一个最大容量为3的缓存:

  1. import java.util.HashMap;
  2. import java.util.Map;
  3. class LRUCache<K, V> {
  4. private int capacity;
  5. private Map<K, Node<K,V>> cache;
  6. private Node<K,V> head;
  7. private Node<K,V> tail;
  8. public LRUCache(int capacity) {
  9. this.capacity = capacity;
  10. this.cache = new HashMap<>();
  11. this.head = new Node<>(null, null);
  12. this.tail = new Node<>(null, null);
  13. this.head.next = this.tail;
  14. this.tail.prev = this.head;
  15. }
  16. public V get(K key) {
  17. if (!cache.containsKey(key)) {
  18. return null;
  19. }
  20. Node<K,V> node = cache.get(key);
  21. remove(node);
  22. addFirst(node);
  23. return node.value;
  24. }
  25. public void put(K key, V value) {
  26. if (cache.containsKey(key)) {
  27. Node<K,V> node = cache.get(key);
  28. node.value = value;
  29. remove(node);
  30. addFirst(node);
  31. } else {
  32. if (cache.size() == capacity) {
  33. Node<K,V> node = removeLast();
  34. cache.remove(node.key);
  35. }
  36. Node<K,V> node = new Node<>(key, value);
  37. cache.put(key, node);
  38. addFirst(node);
  39. }
  40. }
  41. private void remove(Node<K,V> node) {
  42. node.prev.next = node.next;
  43. node.next.prev = node.prev;
  44. }
  45. private void addFirst(Node<K,V> node) {
  46. node.next = head.next;
  47. node.prev = head;
  48. head.next.prev = node;
  49. head.next = node;
  50. }
  51. private Node<K,V> removeLast() {
  52. Node<K,V> node = tail.prev;
  53. remove(node);
  54. return node;
  55. }
  56. private static class Node<K, V> {
  57. K key;
  58. V value;
  59. Node<K,V> prev;
  60. Node<K,V> next;
  61. public Node(K key, V value) {
  62. this.key = key;
  63. this.value = value;
  64. }
  65. }
  66. }

在这个例子中,我们使用了一个哈希表

  1. cache
来存储缓存数据的键值对,同时使用了一个双向链表来维护缓存数据的访问顺序,其中
  1. head
  1. tail
分别表示链表头和链表尾,每次访问缓存时,我们将访问的数据节点移动到链表头,当缓存满时,淘汰链表尾部的节点即可。

注意,为了方便起见,我们在链表头和链表尾分别添加了一个哨兵节点

  1. head
  1. tail
,这样就不需要在代码中处理链表为空的情况了。

下面是一个使用双向链表实现LRU缓存淘汰算法的例子,假设我们要实现一个最大容量为3的缓存:

  1. import java.util.HashMap;
  2. import java.util.Map;
  3. class LRUCache<K, V> {
  4. private int capacity;
  5. private Map<K, Node<K,V>> cache;
  6. private Node<K,V> head;
  7. private Node<K,V> tail;
  8. public LRUCache(int capacity) {
  9. this.capacity = capacity;
  10. this.cache = new HashMap<>();
  11. this.head = new Node<>(null, null);
  12. this.tail = new Node<>(null, null);
  13. this.head.next = this.tail;
  14. this.tail.prev = this.head;
  15. }
  16. public V get(K key) {
  17. if (!cache.containsKey(key)) {
  18. return null;
  19. }
  20. Node<K,V> node = cache.get(key);
  21. remove(node);
  22. addFirst(node);
  23. return node.value;
  24. }
  25. public void put(K key, V value) {
  26. if (cache.containsKey(key)) {
  27. Node<K,V> node = cache.get(key);
  28. node.value = value;
  29. remove(node);
  30. addFirst(node);
  31. } else {
  32. if (cache.size() == capacity) {
  33. Node<K,V> node = removeLast();
  34. cache.remove(node.key);
  35. }
  36. Node<K,V> node = new Node<>(key, value);
  37. cache.put(key, node);
  38. addFirst(node);
  39. }
  40. }
  41. private void remove(Node<K,V> node) {
  42. node.prev.next = node.next;
  43. node.next.prev = node.prev;
  44. }
  45. private void addFirst(Node<K,V> node) {
  46. node.next = head.next;
  47. node.prev = head;
  48. head.next.prev = node;
  49. head.next = node;
  50. }
  51. private Node<K,V> removeLast() {
  52. Node<K,V> node = tail.prev;
  53. remove(node);
  54. return node;
  55. }
  56. private static class Node<K, V> {
  57. K key;
  58. V value;
  59. Node<K,V> prev;
  60. Node<K,V> next;
  61. public Node(K key, V value) {
  62. this.key = key;
  63. this.value = value;
  64. }
  65. }
  66. }

在这个例子中,我们使用了一个哈希表

  1. cache
来存储缓存数据的键值对,同时使用了一个双向链表来维护缓存数据的访问顺序,其中
  1. head
  1. tail
分别表示链表头和链表尾,每次访问缓存时,我们将访问的数据节点移动到链表头,当缓存满时,淘汰链表尾部的节点即可。

注意,为了方便起见,我们在链表头和链表尾分别添加了一个哨兵节点

  1. head
  1. tail
,这样就不需要在代码中处理链表为空的情况了。

以上就是JavaScript怎么实现LRU缓存淘汰算法的详细内容,更多关于JavaScript怎么实现LRU缓存淘汰算法的资料请关注九品源码其它相关文章!