Skip to content

refactor: LFUCache #5369

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 23, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
public class LFUCache<K, V> {

private class Node {

private K key;
private final K key;
private V value;
private int frequency;
private Node previous;
Expand All @@ -26,67 +25,67 @@ private class Node {

private Node head;
private Node tail;
private Map<K, Node> map = null;
private Integer capacity;
private final Map<K, Node> cache;
private final int capacity;
private static final int DEFAULT_CAPACITY = 100;

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.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
* @returns <V> object corresponding to the key passed as parameter, returns null if <K> key is
* not present in the cache
* @param key The key to look up.
* @return The value associated with the key, or null if the key is not present.
*/
public V get(K key) {
if (this.map.get(key) == null) {
Node node = cache.get(key);
if (node == null) {
return null;
}

Node node = map.get(key);
removeNode(node);
node.frequency += 1;
addNodeWithUpdatedFrequency(node);

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 <V> value which is to be stored in the cache
* @param key The key to insert or update.
* @param value The value to insert or update.
*/
public void put(K key, V value) {
if (map.containsKey(key)) {
Node node = map.get(key);
if (cache.containsKey(key)) {
Node node = cache.get(key);
node.value = value;
node.frequency += 1;
removeNode(node);
addNodeWithUpdatedFrequency(node);
} else {
if (map.size() >= capacity) {
map.remove(this.head.key);
if (cache.size() >= capacity) {
cache.remove(this.head.key);
removeNode(head);
}
Node node = new Node(key, value, 1);
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) {
if (tail != null && head != null) {
Expand Down Expand Up @@ -123,9 +122,9 @@ private void addNodeWithUpdatedFrequency(Node node) {
}

/**
* 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) {
if (node.previous != null) {
Expand Down