LRU算法
1 package com.daoyouzhu; 2 3 import java.util.Hashtable; 4 import java.util.Map; 5 6 /** 7 * LRU 最近未使用删除 8 * 核心思想:1.需要一个数据载体类,来存放 9 * 2.需要一个操作载体类的方法,用来完成数据的添加删除等 10 * 3.我需要维护一个hashMap,来判断是否存在数据 11 * 个人认为,对于链表的操作,特别是新节点加入到链表里或者删除,操作前后指向,从本节点开始 12 */ 13 public class RedisLRUDemo { 14 class Node<K, V> { 15 K key; 16 V value; 17 Node<K, V> prev; 18 Node<K, V> next; 19 20 public Node() { 21 prev = next = null; 22 } 23 24 public Node(K key, V value) { 25 this.key = key; 26 this.value = value; 27 prev = next = null; 28 } 29 } 30 31 class DoubleLinkedDemo<K, V> { 32 Node<K, V> head; 33 Node<K, V> tail; 34 35 public DoubleLinkedDemo() { 36 head = new Node<>(); 37 tail = new Node<>(); 38 head.next = tail; 39 tail.prev = head; 40 } 41 42 public void addHead(Node<K, V> node) { 43 node.prev = head; 44 node.next = head.next; 45 head.next.prev = node; 46 head.next = node; 47 } 48 49 public void delTail(Node<K, V> node) { 50 node.prev.next = node.next; 51 node.next.prev = node.prev; 52 node.prev = null; 53 node.next = null; 54 } 55 56 public Node<K, V> getLast() { 57 return tail.prev; 58 } 59 } 60 61 DoubleLinkedDemo<Integer, Integer> doubleLinkedDemo; 62 Map<Integer, Node<Integer, Integer>> map; 63 private int size; 64 65 public RedisLRUDemo(int size) { 66 this.size = size; 67 doubleLinkedDemo = new DoubleLinkedDemo<>(); 68 map = new Hashtable<>(); 69 } 70 71 public int get(int key) { 72 if (!map.containsKey(key)) { 73 return -1; 74 } 75 Node<Integer, Integer> node = map.get(key); 76 doubleLinkedDemo.delTail(node); 77 doubleLinkedDemo.addHead(node); 78 return node.value; 79 } 80 81 public void put(int key, int value) { 82 if (map.containsKey(key)) { 83 Node<Integer, Integer> node = map.get(key); 84 doubleLinkedDemo.delTail(node); 85 node.value = value; 86 doubleLinkedDemo.addHead(node); 87 map.put(key, node); 88 } else { 89 if (size == map.size()) {//满了 90 Node<Integer, Integer> lastNode = doubleLinkedDemo.getLast(); 91 map.remove(lastNode.key); 92 doubleLinkedDemo.delTail(lastNode); 93 } 94 Node<Integer, Integer> newNode = new Node<>(key, value); 95 map.put(key, newNode); 96 doubleLinkedDemo.addHead(newNode); 97 } 98 } 99 100 public static void main(String[] args) { 101 RedisLRUDemo redisLRUDemo = new RedisLRUDemo(3); 102 redisLRUDemo.put(1, 1); 103 redisLRUDemo.put(2, 2); 104 redisLRUDemo.put(3, 3); 105 System.out.println(redisLRUDemo.map.keySet()); 106 107 redisLRUDemo.put(4, 1); 108 System.out.println(redisLRUDemo.map.keySet()); 109 110 redisLRUDemo.put(3, 1); 111 System.out.println(redisLRUDemo.map.keySet()); 112 redisLRUDemo.put(3, 1); 113 System.out.println(redisLRUDemo.map.keySet()); 114 redisLRUDemo.put(3, 1); 115 System.out.println(redisLRUDemo.map.keySet()); 116 redisLRUDemo.put(5, 1); 117 System.out.println(redisLRUDemo.map.keySet()); 118 119 System.out.println(redisLRUDemo.doubleLinkedDemo.head); 120 } 121 122 }
执行结果:

流程图1:
流程图2:

描述:如果有ABC三个在队列中,顺序也是head->A->B->C->tail,如果又访问了一次C,就需要将C放在head的后面,将AB后移,顺序变为head->C->A->B->tail,所以要将原来的C删除,新增一个C放在head后,
如果又新来了一个D,那么B就应该被删除,将D放在head后,顺序为head->D->C->A->tail。类似于AQS的底层实现。


浙公网安备 33010602011771号