Skip to content

Commit 621a260

Browse files
authored
Update LRU.java
1 parent e7dfb5a commit 621a260

File tree

1 file changed

+67
-118
lines changed
  • src/main/java/dataStructures/lruCache

1 file changed

+67
-118
lines changed
Lines changed: 67 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,138 +1,87 @@
11
package dataStructures.lruCache;
22

33
import java.util.HashMap;
4-
import java.util.Map;
54

6-
/**
7-
* Implementation of Least Recently Used (LRU) Cache
8-
*
9-
* @param <K> generic type of key to be stored
10-
* @param <V> generic type of associated value corresponding to a given key
11-
* Constructor:
12-
* LRU(int capacity)
13-
* Client methods:
14-
* get(K key)
15-
* put(K key, V value)
16-
* Both methods above run in O(1) average time complexity
17-
*/
18-
public class LRU<K, V> {
19-
private final int cap;
20-
private final Map<K, Node<K, V>> map;
21-
private final Node<K, V> left; // dummy left node to point to the left end
22-
private final Node<K, V> right; // dummy right node to point to the right end
5+
public class doublyLinkedList {
6+
int key;
7+
int val;
8+
doublyLinkedList next;
9+
doublyLinkedList prev;
10+
}
2311

24-
/**
25-
* Helper node class that encapsulates key-value pair and act as linked list to neighbour nodes.
26-
*/
27-
private class Node<K, V> {
28-
private final K key;
29-
private V val;
30-
private Node<K, V> next;
31-
private Node<K, V> prev;
12+
class LRUCache {
13+
doublyLinkedList dllHead;
14+
doublyLinkedList dllTail;
15+
HashMap<Integer, doublyLinkedList> keyToNode = new HashMap();
16+
int capacity;
17+
int lengthOfList = 0;
3218

33-
Node(K key, V value) {
34-
this.key = key;
35-
this.val = value;
36-
this.next = null;
37-
this.prev = null;
38-
}
39-
}
19+
public LRUCache(int capacity) {
20+
this.capacity = capacity;
4021

41-
/**
42-
* Constructs an instance of Least Recently Used Cache.
43-
*
44-
* @param capacity the maximum capacity of the cache.
45-
*/
46-
public LRU(int capacity) {
47-
this.cap = capacity;
48-
this.map = new HashMap<>();
49-
this.left = new Node<>(null, null);
50-
this.right = new Node<>(null, null);
51-
this.left.next = this.right;
52-
this.right.prev = this.left;
53-
}
22+
dllHead = new doublyLinkedList();
23+
dllHead.key = -1;
24+
dllHead.val = -1;
5425

55-
/**
56-
* Helper method to remove the specified node from the doubly linked list
57-
*
58-
* @param node to be removed from the linked list
59-
*/
60-
private void remove(Node<K, V> node) {
61-
Node<K, V> prev = node.prev;
62-
Node<K, V> nxt = node.next;
63-
prev.next = nxt;
64-
nxt.prev = prev;
65-
}
26+
dllTail = new doublyLinkedList();
27+
dllTail.key = -1;
28+
dllTail.val = -1;
6629

67-
/**
68-
* Helper method to insert a node to the right end of the double linked list (Most Recently Used)
69-
*
70-
* @param node to be inserted
71-
*/
72-
private void insert(Node<K, V> node) {
73-
Node<K, V> prev = this.right.prev;
74-
prev.next = node;
75-
node.prev = prev;
76-
node.next = this.right;
77-
this.right.prev = node;
30+
dllHead.prev = null;
31+
dllHead.next = dllTail;
32+
dllTail.prev = dllHead;
33+
dllTail.next = null;
7834
}
35+
36+
public int get(int key) {
37+
if(!keyToNode.containsKey(key)) return -1;
7938

80-
/**
81-
* return the value of the key if it exists; otherwise null
82-
*
83-
* @param key whose value, if exists, to be obtained
84-
*/
85-
public V get(K key) {
86-
if (this.map.containsKey(key)) {
87-
Node<K, V> node = this.map.get(key);
88-
this.remove(node);
89-
this.insert(node);
90-
return node.val;
91-
}
92-
return null;
39+
doublyLinkedList temp = keyToNode.get(key);
40+
temp.prev.next = temp.next;
41+
temp.next.prev = temp.prev;
42+
43+
temp.next = dllHead.next;
44+
dllHead.next.prev = temp;
45+
temp.prev = dllHead;
46+
dllHead.next = temp;
47+
48+
return keyToNode.get(key).val;
9349
}
50+
51+
public void put(int key, int value) {
52+
boolean addingNewNode = true;
53+
54+
doublyLinkedList newlyCached;
9455

95-
/**
96-
* Update the value of the key if the key exists.
97-
* Otherwise, add the key-value pair to the cache.
98-
* If the number of keys exceeds the capacity from this operation, evict the least recently used key
99-
*
100-
* @param key the key
101-
* @param val the associated value
102-
*/
103-
public void update(K key, V val) {
104-
if (this.map.containsKey(key)) {
105-
Node<K, V> node = this.map.get(key);
106-
this.remove(node);
107-
node.val = val;
108-
this.insert(node); // make most recently used
109-
} else {
110-
Node<K, V> node = new Node<>(key, val);
111-
this.map.put(node.key, node);
112-
this.insert(node);
56+
if(!keyToNode.containsKey(key)) {
57+
newlyCached = new doublyLinkedList();
58+
newlyCached.key = key;
59+
newlyCached.val = value;
60+
keyToNode.put(key, newlyCached);
11361
}
62+
else {
63+
newlyCached = keyToNode.get(key);
64+
newlyCached.val = value;
65+
addingNewNode = false;
11466

115-
if (this.map.size() > this.cap) { // evict LRU since capacity exceeded
116-
Node<K, V> toRemove = this.left.next;
117-
this.map.remove(toRemove.key);
118-
this.remove(toRemove);
67+
newlyCached.prev.next = newlyCached.next;
68+
newlyCached.next.prev = newlyCached.prev;
11969
}
120-
}
12170

122-
/**
123-
* Custom print for testing
124-
* prints from LRU to MRU (Most recently used)
125-
*/
126-
public void print() {
127-
Node<K, V> trav = this.left.next;
128-
System.out.print("Dummy");
129-
while (trav != this.right) {
130-
System.out.print(" ->");
131-
System.out.print(trav.key);
132-
System.out.print(",");
133-
System.out.print(trav.val);
134-
trav = trav.next;
71+
newlyCached.next = dllHead.next;
72+
dllHead.next.prev = newlyCached;
73+
newlyCached.prev = dllHead;
74+
dllHead.next = newlyCached;
75+
76+
if(addingNewNode) {
77+
if(lengthOfList == capacity) {
78+
keyToNode.remove(dllTail.prev.key);
79+
dllTail.prev.prev.next = dllTail;
80+
dllTail.prev = dllTail.prev.prev;
81+
}
82+
else {
83+
lengthOfList++;
84+
}
13585
}
136-
System.out.println();
13786
}
13887
}

0 commit comments

Comments
 (0)