1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
| public class LFUCacheUsingTwoWayLinkedList<K, V> {
public CacheNodeQueue tail;
public int capacity;
public HashMap<K, Pair<Integer,V>> getMap() { HashMap<K, Pair<Integer,V>> hashMap = new HashMap<>(); map.forEach((x,y)->{ hashMap.put(x,Pair.of(y.currentLevelQueue().frequency,y.value)); }); return hashMap; }
private HashMap<K, CacheNode<K,V>> map;
public LFUCacheUsingTwoWayLinkedList(int capacity) { this.capacity = capacity; map = new HashMap<K, CacheNode<K,V>>(capacity); }
private void moveNodeToNextLevelQueueHead(CacheNode n){ CacheNodeQueue current = n.currentLevelQueue(); int valueFrequency= current.frequency+1; CacheNodeQueue nextLevel = current.high; if(current.isHeadQueue()){ if(current.isSingleQueue()) { current.frequency++; }else { unlinkNode(n); new CacheNodeQueue(current, null, n, n, valueFrequency); } }else { if (current.high.frequency == valueFrequency) { if(current.isSingleQueue()) { unlinkNode(n); nextLevel.addNodeToHead(n); if(current.isTailQueue()){ tail = nextLevel; nextLevel.low = null; }else { current.low.high = nextLevel; nextLevel.low = current.low; } }else { unlinkNode(n); nextLevel.addNodeToHead(n); } }else if (current.high.frequency > valueFrequency) { if(current.isSingleQueue()) { if(current.isTailQueue()){ current.frequency++; }else { unlinkNode(n); nextLevel = new CacheNodeQueue(current, current.high, n, n, valueFrequency); current.low.high = nextLevel; nextLevel.low = current.low; } }else { unlinkNode(n); new CacheNodeQueue(current, current.high, n, n, valueFrequency); } } } }
public V get(K key) { CacheNode n = map.get(key); if (n == null) { return null; } moveNodeToNextLevelQueueHead(n); return (V) n.value; }
public void put(K key, V value) { if (capacity == 0) { return; }
CacheNode cn = map.get(key); if (cn != null) { cn.value = value; moveNodeToNextLevelQueueHead(cn); return; } if (map.size() == capacity) { CacheNodeQueue current = tail; if(current.isSingleQueue()){ tail = current.high; } CacheNode node= unlinkNode(current.tail); map.remove(node.key);
} CacheNode n = new CacheNode(key, value); if (this.tail == null) { CacheNodeQueue nq = new CacheNodeQueue(null, null, n, n,0); this.tail = nq; } else if (this.tail.frequency == 0) { this.tail.addNodeToHead(n); } else { CacheNodeQueue nq = new CacheNodeQueue( null,this.tail, n, n,0); this.tail = nq; } map.put(key, n); } }
|