LRU算法实现, 参考LinkedHashMap

直接上代码

  1. package LRUCache;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. /**
  5. * @author RYH
  6. * @description lru算法, 参考linkedHashmap
  7. * @date 2022/2/21
  8. **/
  9. public class LRUCacheDemo<K, V> {
  10. /**
  11. * 容量
  12. */
  13. private final int capacity;
  14. /**
  15. * 用来存放key和节点, 方便快速查找
  16. */
  17. Map<Integer, Node<Integer, Integer>> map;
  18. /**
  19. * 用来存放各个数据节点
  20. */
  21. Node.DoubleLinkedList<Integer, Integer> doubleLinkedList;
  22. public LRUCacheDemo(int capacity) {
  23. this.capacity = capacity;
  24. map = new HashMap<>();
  25. doubleLinkedList = new Node.DoubleLinkedList<>();
  26. }
  27. /**
  28. * 获取数据
  29. * <p>
  30. * 如果数据被使用, 则需要更新数据位置
  31. *
  32. * @param key 数据key
  33. * @return 存放的value
  34. */
  35. public int get(int key) {
  36. if (!map.containsKey(key)) {
  37. return -1;
  38. }
  39. Node<Integer, Integer> node = map.get(key);
  40. doubleLinkedList.removeNode(node);
  41. doubleLinkedList.addHead(node);
  42. return node.value;
  43. }
  44. /**
  45. * 数据新增
  46. * <p>
  47. * 如果存在数据key,则更新相应的值(类似hashmap),并且更新数据位置,
  48. * 如果不存在则新增,
  49. *
  50. * @param key 数据key
  51. * @param value 数据值
  52. */
  53. public void put(int key, int value) {
  54. if (map.containsKey(key)) {
  55. Node<Integer, Integer> node = map.get(key);
  56. node.value = value;
  57. map.put(key, node);
  58. doubleLinkedList.removeNode(node);
  59. doubleLinkedList.addHead(node);
  60. } else {
  61. if (map.size() == this.capacity) {
  62. Node<Integer, Integer> last = doubleLinkedList.getLast();
  63. map.remove(last.key);
  64. doubleLinkedList.removeNode(last);
  65. }
  66. Node<Integer, Integer> node = new Node<>(key, value);
  67. map.put(key, node);
  68. doubleLinkedList.addHead(node);
  69. }
  70. }
  71. /**
  72. * 内部节点类 用于存放数据节点
  73. *
  74. * @param <K> key
  75. * @param <V> value
  76. */
  77. static class Node<K, V> {
  78. K key;
  79. V value;
  80. Node<K, V> prev;
  81. Node<K, V> next;
  82. Node() {
  83. this.prev = this.next = null;
  84. }
  85. Node(K key, V value) {
  86. this.key = key;
  87. this.value = value;
  88. this.prev = this.next = null;
  89. }
  90. /**
  91. * 内部双向链表
  92. * 记录数据书否被更新, 数据被操作, 则数据移到队列头部
  93. *
  94. * @param <K>
  95. * @param <V>
  96. */
  97. static class DoubleLinkedList<K, V> {
  98. Node<K, V> head;
  99. Node<K, V> tail;
  100. public DoubleLinkedList() {
  101. head = new Node<>();
  102. tail = new Node<>();
  103. head.next = tail;
  104. tail.prev = head;
  105. }
  106. /**
  107. * 向链表头部插入数据
  108. *
  109. * @param node 数据节点
  110. */
  111. public void addHead(Node<K, V> node) {
  112. node.next = head.next;
  113. node.prev = head;
  114. head.next.prev = node;
  115. head.next = node;
  116. }
  117. /**
  118. * 移除链表数据
  119. *
  120. * @param node 数据节点
  121. */
  122. public void removeNode(Node<K, V> node) {
  123. node.prev.next = node.next;
  124. node.next.prev = node.prev;
  125. node.prev = null;
  126. node.next = null;
  127. }
  128. /**
  129. * 获取数据最后一个节点
  130. *
  131. * @return 最后一个数据节点
  132. */
  133. public Node<K, V> getLast() {
  134. return tail.prev;
  135. }
  136. }
  137. }
  138. }