• 设计LRU缓存结构


    1. 什么是LRU缓存?

    LRU缓存是一种基于最近访问原则缓存策略。它的核心思想是,当缓存空间满时,优先淘汰最近最少使用的数据。这种策略的好处是,可以保留最常访问的数据,提高缓存命中率,从而提高系统性能

    2. LRU缓存的实现原理

    LRU缓存的实现可以借助哈希表和双向链表。哈希表用于快速查找缓存中的数据,而双向链表用于维护数据的访问顺序。每当访问一个数据时,如果数据已经存在于缓存中,将其移动到链表的头部;如果数据不存在于缓存中,将其添加到链表的头部。当缓存空间满时,淘汰链表尾部的数据即可。

    3. LRU缓存的实现步骤

    - 初始化缓存大小和哈希表

    - 访问数据时,检查哈希表中是否存在该数据

    - 如果存在,将数据移动到链表头部

    - 如果不存在,将数据添加到链表头部,并在哈希表中添加对应的键值对

    - 如果缓存已满,删除链表尾部的数据,并在哈希表中删除对应的键值对

    4.具体实现

    1. public class LRUCache {
    2. //链表存储键值对(旧数据靠链表尾)
    3. class Node {
    4. int key;
    5. int value;
    6. Node prev;
    7. Node next;
    8. public Node(int key, int value) {
    9. this.key = key;
    10. this.value = value;
    11. }
    12. }
    13. //缓存大小
    14. private int capacity;
    15. //缓存
    16. private Map cache;
    17. //头指针
    18. private Node head;
    19. //尾指针组成双向链表
    20. private Node tail;
    21. //初始化缓存
    22. public LRUCache(int capacity) {
    23. this.capacity = capacity;
    24. this.cache = new HashMap<>();
    25. this.head = new Node(0, 0);
    26. this.tail = new Node(0, 0);
    27. head.next = tail;
    28. tail.next = head;
    29. }
    30. //获取缓存数据
    31. public int get(int key) {
    32. if (cache.containsKey(key)) {
    33. Node node = cache.get(key);
    34. //更新数据(把该数据放到链表头)
    35. removeNode(node);
    36. addToHead(node);
    37. return node.value;
    38. }
    39. //不存在则返回-1
    40. return -1;
    41. }
    42. //存放数据
    43. public void put(int key, int value) {
    44. //包含则更新,不然新增
    45. if (cache.containsKey(key)) {
    46. Node node = cache.get(key);
    47. node.value = value;
    48. //更新数据
    49. removeNode(node);
    50. addToHead(node);
    51. } else {
    52. //大于容量,则删除最后一个值(最不经常使用的数据)
    53. if (cache.size() == capacity) {
    54. Node tailPrev = tail.prev;
    55. removeNode(tailPrev);
    56. cache.remove(tailPrev.key);
    57. }
    58. Node newNode = new Node(key, value);
    59. cache.put(key, newNode);
    60. addToHead(newNode);
    61. }
    62. }
    63. //删除链表节点
    64. private void removeNode(Node node) {
    65. Node prevNode = node.prev;
    66. Node nextNode = node.next;
    67. prevNode.next = nextNode;
    68. nextNode.prev = prevNode;
    69. }
    70. //头部插入节点
    71. private void addToHead(Node node) {
    72. Node nextNode = head.next;
    73. head.next = node;
    74. node.prev = head;
    75. node.next = nextNode;
    76. nextNode.prev = node;
    77. }
    78. }

  • 相关阅读:
    uniapp&小程序打开地图导航
    LeetCode每日一题:1668. 最大重复子字符串 (简单) 字符串查找/枚举/kmp+dp/序列dp
    javascript算法之从会用到理解 - 贪心算法
    webpack5学习进阶:Library、模块联邦、构建优化
    无线网络中的联邦学习:优化模型设计与分析
    微信小程序——video视频全屏展示
    Linux-安装jenkins
    【SA8295P 源码分析 (三)】121 - MAX9295A 加串器芯片手册分析 及初始化参数分析
    C语言模拟最简单的计算机
    【HashMap】1w字解析HashMap底层部分源码
  • 原文地址:https://blog.csdn.net/DU9999999/article/details/133036160