LRU cache 实现

169 阅读1分钟
package stardustman.github.io;

//
//LRUCache cache = new LRUCache( 2 /* capacity */ );
//        cache.put(1, 1);
//        cache.put(2, 2);
//        cache.get(1); // returns 1
//        cache.put(3, 3); // evicts key 2
//        cache.get(2); // returns -1 (not found)
//        cache.put(4, 4); // evicts key 1
//        cache.get(1); // returns -1 (not found)
//        cache.get(3); // returns 3
//        cache.get(4); // returns 4
//        (要求包含unit,test ,testcase)

class Node {
    int k;
    int v;
    public Node(int k,int v){
        this.k = k;
        this.v = v;
    }
}

public class LRUCache {
    private int capacity; // cache 容量
    private int size; // cache 已经存放的元素个数
    private Node[] cache; // 使用数组作为队列,下标越小的元素,越是最近最少使用的元素

    public LRUCache(int capacity) {
        this.capacity = capacity;
        this.size = 0;
        this.cache = new Node[capacity];
    }

    public boolean isEmpty() {
        if ((size > 0) && (size <= capacity)) {
            return false;
        }
        return true;
    }

    public boolean isFull() {
        if (size == capacity) {
            return true;
        }
        return false;
    }

    public boolean checkIndex(int index){
        if ((index >=0) && (index < size)){
            return true;
        }
        return false;
    }

    public int find(Node target){
        for (int i = 0; i < size; i++) {
            if (cache[i].k == target.k && cache[i].v == target.v){
                return i;
            }
        }
        return -1;
    }

    public int findValueByKey(int key){
        for (int i = 0; i < size; i++) {
            if (cache[i].k == key){
                return cache[i].v;
            }
        }
        return -1;
    }

    public void replace(int index){
        if(!checkIndex(index)){
            throw new IllegalArgumentException("index wrong" + index );
        }
        if (index == size -1){
            return;
        } else {
            Node temp = cache[index];
            // 以 index 为界, index 之后的前移
            for (int i = index ; i < size - 1 ; i++) {
                 cache[i] = cache[i + 1];
            }
            cache[size - 1] = temp;
        }

    }

    public void put(int k, int v) {
         Node candidate = new Node(k,v);
         int res = find(candidate);
         if (res == -1){ // 没找到
             if(!isFull()){
                 cache[size] = candidate;
                 size++;
             } else {
               System.out.println("evicts key " + cache[size - 1].k);
               cache[size - 1] = candidate;
             }
         } else { // 找到了要存放的元素,重新放置这个元素。
             replace(res);
         }
    }

    public int get(int key) {
       if (isEmpty()){
           return -1;
       } else {
           int value = findValueByKey(key);
           Node temp = new Node(key,value);
           int index = find(temp);
           if (checkIndex(index)){
               replace(index);
           }
           System.out.println("returns " + value);
           return value;
       }
    }

    public static void main(String[] args) {
        LRUCache cache = new LRUCache( 2 /* capacity */ );
        cache.put(1, 1);
        cache.put(2, 2);
        cache.get(1); // returns 1
        cache.put(3, 3); // evicts key 2
        cache.get(2); // returns -1 (not found)
        cache.put(4, 4); // evicts key 1
        cache.get(1); // returns -1 (not found)
        cache.get(3); // returns 3
        cache.get(4); // returns 4
    }
}