一份利用LinkedHashMap实现的简易LRU。注意,LinkedHashMap 继承自 HashMap,get方法直接使用的HashMap提供的。
public static void main(String[] args) { int[][] operators = new int[][] { new int[] { 1, 1, 1 }, new int[] { 1, 2, 2 }, new int[] { 1, 3, 2 }, new int[] { 2, 1 }, new int[] { 1, 4, 4 }, new int[] { 1, 100, 4 }, new int[] { 2, 3} }; int[] arr = LRUCache_NowCode.LRU(operators, 4); System.out.println(Arrays.toString(arr)); } public static int[] LRU (int[][] operators, int k) { // 声明一个linkedHashMap,容量为k,负载因子为0.75,按照获取顺序排序 // 也就是说,新加进来的节点,都会在队列的尾部 // 队列的头部,一定是最近使用最少的那个节点 LinkedHashMap<Integer,Integer> lru = new LinkedHashMap<Integer,Integer>(k,0.75f,true); List<Integer> list = new ArrayList<Integer>(); for(int[] ope : operators){ int tmp = ope[0]; int key = ope[1]; //增加缓存 if(tmp == 1){ //如果已经存在key,则直接删除旧值 if(lru.containsKey(key)){ lru.remove(key); }else if(lru.size() >= k){ //如果容量已经满了,则删除排在队列第一个的元素 lru.remove(lru.keySet().iterator().next()); } //将新的数据加在队列的尾部 lru.put(key,ope[2]); }else if(tmp == 2){ //获取缓存值 if(lru.containsKey(key)){ // 直接调用的hashMap中的值进行处理 int value = lru.get(key); //移除旧值 lru.remove(key); //增加新值 lru.put(key,value); //拿到结果并保存 list.add(value); }else { list.add(-1); } } printLinkMap(lru); } int[] res = new int[list.size()]; for(int i = 0; i < res.length; i++){ res[i] = list.get(i); } return res; } public LRUCache_NowCode(int k) { this.size = k; } private int size = -1; // 容量 public static void printLinkMap(LinkedHashMap<Integer,Integer> lru) { Iterator<Integer> iter = lru.keySet().iterator(); while(iter != null && iter.hasNext()) { System.out.print(" v ->" + iter.next()); } System.out.println(); }
一份利用hashMap实现的LRU
node类
class Node{ private int v; private Object k; private Node next; private Node pre; public Node(Object key,int value) { this.v = value; this.k = key; } public int getV() { return v; } public void setV(int v) { this.v = v; } public Node getNext() { return next; } public void setNext(Node next) { this.next = next; } public Node getPre() { return pre; } public void setPre(Node pre) { this.pre = pre; } public Object getK() { return k; } public void setK(Object k) { this.k = k; } }
LRUcache类
public class LRUCache_NowCode { public static Object[] LRU(int[][] operators, int k) { if (operators.length <= 0 || k <= 0) { return null; } List<Object> reList = new ArrayList<Object>(); LRUCache_NowCode cache = new LRUCache_NowCode(k); for (int[] tmpArr : operators) { int key = tmpArr[0]; switch (key) { case 1: cache.set(Integer.valueOf(tmpArr[1]), Integer.valueOf(tmpArr[2])); break; case 2: reList.add(cache.get(Integer.valueOf(tmpArr[1]))); break; default: break; } } Object[] reArr = new Object[reList.size()]; for (int i = 0; i < reList.size(); i++) { reArr[i] = reList.get(i); } return reArr; } public LRUCache_NowCode(int k) { this.size = k; } private int size = -1; // 容量 private Node head = null; private Node tail = null; private Map<Object, Node> cacheMap = new HashMap<Object, Node>(); public void set(Object key, int value) { System.out.println("set key -> " + key + " value -> " + value); Node node = cacheMap.get(key); if (node == null) { node = new Node(key,value); cacheMap.put(key, node); } else { // 将节点从链表中移除 if (node.getNext() != null) { node.getNext().setPre(node.getPre()); } if (node.getPre() != null) { node.getPre().setNext(node.getNext()); } node.setV(value); } // 头尾节点给默认值 if (head == null || tail == null) { head = tail = node; } // 容量判断 if (cacheMap.size() > size) { //移除尾指针 cacheMap.remove(tail.getK()); //移动尾指针 tail = tail.getPre();
if(tail != null) tail.setNext(null); } // 当前节点不是头结点 if (head != node) { head.setPre(node); node.setNext(head); node.setPre(null); head = node; } printHead(head); printTail(tail); System.out.println("-----"); } public static void printHead(Node node) { System.out.print(node.getV()); Node tmp = node; while (tmp.getNext() != null) { tmp = tmp.getNext(); System.out.print(" next -> " + tmp.getV()); } System.out.println(); } public static void printTail(Node node) { System.out.print(node.getV()); Node tmp = node; while (tmp.getPre() != null) { tmp = tmp.getPre(); System.out.print(" pre -> " + tmp.getV()); } System.out.println(); } /** * 移到队列头部 * * @param i * @return */ public Object get(Object key) { System.out.println("get key -> " + key); Node existNode = cacheMap.get(key); if (existNode == null) { return -1; } Node n = existNode.getNext(); Node p = existNode.getPre(); if (p != null) { p.setNext(n); } if (n != null) { n.setPre(p); } existNode.setNext(head); head.setPre(existNode); existNode.setPre(null); head = existNode; // 如果恰好查的是尾节点,那将尾指针前移一个单位 if (tail == existNode) { tail = p; tail.setNext(null); } return existNode.getV(); } }
main方法测试
public static void main(String[] args) { int[][] operators = new int[][] { new int[] { 1, 1, 1 }, new int[] { 1, 2, 2 }, new int[] { 1, 3, 2 }, new int[] { 2, 1 }, new int[] { 1, 4, 4 }, new int[] { 2, 2 } }; Object[] arr = LRUCache_NowCode.LRU(operators, 3); System.out.println(Arrays.toString(arr)); }
此处直接将key保存在了对象中,可以根据对象之间的引用关系直接找到前后的key,简化处理头尾节点时逻辑。