LRU

一份利用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,简化处理头尾节点时逻辑。

 

posted @ 2020-11-22 10:18  kirkvicent  阅读(167)  评论(0编辑  收藏  举报