LRU cache in Java with Generics and O(1) operations

后端 未结 14 1696
刺人心
刺人心 2020-12-02 07:12

This is a question that comes up a lot in job interviews. The idea is to define a data structure instead of using Java\'s built in LinkedHashMap.

An LRU cache delete

14条回答
  •  离开以前
    2020-12-02 08:01

    Here is the java implementation

    import java.util.HashMap;
    import java.util.Map;
    
    import com.nadeem.app.dsa.adt.Cache;
    // Kind of linkedHashMap
    public class LRUCache  implements Cache {
    
    private int capacity;
    private Node head, tail;
    private Map> map;
    
    private static final int DEFAULT_CAPACITY = 10;
    
    public LRUCache(int capacity) {
        this.capacity = capacity;
        this.map = new HashMap>();
    }
    
    public LRUCache() {
        this(DEFAULT_CAPACITY);
    }
    
    @Override
    public V get(K key) {
        V result = null;
        Node node = this.map.get(key);
        if (node != null) {
            result = node.value;
            remove(node);
            addAsHead(node);
        }
        return result;
    }
    
    @Override
    public void set(K key, V value) {
        Node node = this.map.get(key);
        if (node == null) {
            Node temp = new Node(key, value);
            if (this.map.size() < this.capacity) {
                addAsHead(temp);
            } else {
                this.map.remove(this.tail.key);
                remove(this.tail);
                addAsHead(temp);
            }
            this.map.put(key, temp);
        } else {
            node.value = value;
            remove(node);
            addAsHead(node);
        }
    }
    
    private void remove(Node node) {
    
        if (node.pre == null) {
            this.head = node.next;
        } else {
            node.pre.next = node.next;
        }
    
        if (node.next == null) {
            this.tail = node.pre;
        } else {
            node.next.pre = node.pre;
        }       
    }
    
    private void addAsHead(Node node) {
        if (this.head == null) {
            this.head = node;
            this.tail = node;
        } else {
            this.head.pre = node;
            node.next = this.head;
            this.head = node;
        }
    }
    
    @Override
    public void remove(K key) {
        Node node = this.map.get(key);
        if (node != null) {
            this.remove(node);
        }       
    }
    
    private static class Node  {
        public S key;
        public T value;
        Node pre;
        Node next;
    
        Node(S key, T value) {
            this.key = key;
            this.value = value;
        }       
    }
    
    @Override
    public int size() {
        return this.map.size();
    }
    

    }

    Here is the unit test

    public class LRUCacheTest {
    
    private LRUCache cache;
    
    @Before
    public void doBeforeEachTestCase() {
        this.cache = new LRUCache(2);
    }
    
    @Test
    public void setTest() {
        this.cache.set(1, 1);
        assertThat(this.cache.size(), equalTo(1));
        assertThat(this.cache.get(1), equalTo(1));
    
        this.cache.set(2, 2);
        assertThat(this.cache.size(), equalTo(2));
        assertThat(this.cache.get(2), equalTo(2));
    
        this.cache.set(3, 3);
        assertThat(this.cache.size(), equalTo(2));
        assertThat(this.cache.get(3), equalTo(3));
    
        this.cache.set(1, 3);
        assertThat(this.cache.size(), equalTo(2));
        assertThat(this.cache.get(1), equalTo(3));
    
        assertThat(this.cache.get(4), equalTo(null));
    }
    

    }

提交回复
热议问题