refactor: LFUCache (#5369)

This commit is contained in:
Alex Klymenko
2024-08-23 13:23:16 +02:00
committed by GitHub
parent d7b60be7d1
commit 844aeaf701

View File

@ -10,8 +10,7 @@ import java.util.Map;
public class LFUCache<K, V> { public class LFUCache<K, V> {
private class Node { private class Node {
private final K key;
private K key;
private V value; private V value;
private int frequency; private int frequency;
private Node previous; private Node previous;
@ -26,67 +25,67 @@ public class LFUCache<K, V> {
private Node head; private Node head;
private Node tail; private Node tail;
private Map<K, Node> map = null; private final Map<K, Node> cache;
private Integer capacity; private final int capacity;
private static final int DEFAULT_CAPACITY = 100; private static final int DEFAULT_CAPACITY = 100;
public LFUCache() { public LFUCache() {
this.capacity = DEFAULT_CAPACITY; this(DEFAULT_CAPACITY);
} }
public LFUCache(Integer capacity) { public LFUCache(int capacity) {
if (capacity <= 0) {
throw new IllegalArgumentException("Capacity must be greater than zero.");
}
this.capacity = capacity; this.capacity = capacity;
this.map = new HashMap<>(); this.cache = new HashMap<>();
} }
/** /**
* This method returns value present in the cache corresponding to the key passed as parameter * Retrieves the value for the given key from the cache. Increases the frequency of the node.
* *
* @param <K> key for which value is to be retrieved * @param key The key to look up.
* @returns <V> object corresponding to the key passed as parameter, returns null if <K> key is * @return The value associated with the key, or null if the key is not present.
* not present in the cache
*/ */
public V get(K key) { public V get(K key) {
if (this.map.get(key) == null) { Node node = cache.get(key);
if (node == null) {
return null; return null;
} }
Node node = map.get(key);
removeNode(node); removeNode(node);
node.frequency += 1; node.frequency += 1;
addNodeWithUpdatedFrequency(node); addNodeWithUpdatedFrequency(node);
return node.value; return node.value;
} }
/** /**
* This method stores <K> key and <V> value in the cache * Adds or updates a key-value pair in the cache. If the cache is full, the least frequently used item is evicted.
* *
* @param <K> key which is to be stored in the cache * @param key The key to insert or update.
* @param <V> value which is to be stored in the cache * @param value The value to insert or update.
*/ */
public void put(K key, V value) { public void put(K key, V value) {
if (map.containsKey(key)) { if (cache.containsKey(key)) {
Node node = map.get(key); Node node = cache.get(key);
node.value = value; node.value = value;
node.frequency += 1; node.frequency += 1;
removeNode(node); removeNode(node);
addNodeWithUpdatedFrequency(node); addNodeWithUpdatedFrequency(node);
} else { } else {
if (map.size() >= capacity) { if (cache.size() >= capacity) {
map.remove(this.head.key); cache.remove(this.head.key);
removeNode(head); removeNode(head);
} }
Node node = new Node(key, value, 1); Node node = new Node(key, value, 1);
addNodeWithUpdatedFrequency(node); addNodeWithUpdatedFrequency(node);
map.put(key, node); cache.put(key, node);
} }
} }
/** /**
* This method stores the node in the cache with updated frequency * Adds a node to the linked list in the correct position based on its frequency.
* *
* @param Node node which is to be updated in the cache * @param node The node to add.
*/ */
private void addNodeWithUpdatedFrequency(Node node) { private void addNodeWithUpdatedFrequency(Node node) {
if (tail != null && head != null) { if (tail != null && head != null) {
@ -123,9 +122,9 @@ public class LFUCache<K, V> {
} }
/** /**
* This method removes node from the cache * Removes a node from the linked list.
* *
* @param Node node which is to be removed in the cache * @param node The node to remove.
*/ */
private void removeNode(Node node) { private void removeNode(Node node) {
if (node.previous != null) { if (node.previous != null) {