4
4
import java .util .Map ;
5
5
6
6
/**
7
- * Java program for LFU Cache (https://en.wikipedia.org/wiki/Least_frequently_used)
7
+ * The {@code LFUCache} class implements a Least Frequently Used (LFU) cache.
8
+ * An LFU cache evicts the least frequently used item when the cache reaches its capacity.
9
+ * It keeps track of how many times each item is used and maintains a doubly linked list
10
+ * for efficient addition and removal of items based on their frequency of use.
11
+ *
12
+ * @param <K> The type of keys maintained by this cache.
13
+ * @param <V> The type of mapped values.
14
+ *
15
+ * <p>
16
+ * Reference: <a href="https://en.wikipedia.org/wiki/Least_frequently_used">LFU Cache - Wikipedia</a>
17
+ * </p>
18
+ *
8
19
* @author Akshay Dubey (https://github.com/itsAkshayDubey)
9
20
*/
10
21
public class LFUCache <K , V > {
11
22
23
+ /**
24
+ * The {@code Node} class represents an element in the LFU cache.
25
+ * Each node contains a key, a value, and a frequency count.
26
+ * It also has pointers to the previous and next nodes in the doubly linked list.
27
+ */
12
28
private class Node {
13
29
private final K key ;
14
30
private V value ;
15
31
private int frequency ;
16
32
private Node previous ;
17
33
private Node next ;
18
34
35
+ /**
36
+ * Constructs a new {@code Node} with the specified key, value, and frequency.
37
+ *
38
+ * @param key The key associated with this node.
39
+ * @param value The value stored in this node.
40
+ * @param frequency The frequency of usage of this node.
41
+ */
19
42
Node (K key , V value , int frequency ) {
20
43
this .key = key ;
21
44
this .value = value ;
@@ -29,10 +52,19 @@ private class Node {
29
52
private final int capacity ;
30
53
private static final int DEFAULT_CAPACITY = 100 ;
31
54
55
+ /**
56
+ * Constructs an LFU cache with the default capacity.
57
+ */
32
58
public LFUCache () {
33
59
this (DEFAULT_CAPACITY );
34
60
}
35
61
62
+ /**
63
+ * Constructs an LFU cache with the specified capacity.
64
+ *
65
+ * @param capacity The maximum number of items that the cache can hold.
66
+ * @throws IllegalArgumentException if the specified capacity is less than or equal to zero.
67
+ */
36
68
public LFUCache (int capacity ) {
37
69
if (capacity <= 0 ) {
38
70
throw new IllegalArgumentException ("Capacity must be greater than zero." );
@@ -42,10 +74,12 @@ public LFUCache(int capacity) {
42
74
}
43
75
44
76
/**
45
- * Retrieves the value for the given key from the cache. Increases the frequency of the node.
77
+ * Retrieves the value associated with the given key from the cache.
78
+ * If the key exists, the node's frequency is increased and the node is repositioned
79
+ * in the linked list based on its updated frequency.
46
80
*
47
- * @param key The key to look up .
48
- * @return The value associated with the key, or null if the key is not present.
81
+ * @param key The key whose associated value is to be returned .
82
+ * @return The value associated with the key, or {@code null} if the key is not present in the cache .
49
83
*/
50
84
public V get (K key ) {
51
85
Node node = cache .get (key );
@@ -59,10 +93,12 @@ public V get(K key) {
59
93
}
60
94
61
95
/**
62
- * Adds or updates a key-value pair in the cache. If the cache is full, the least frequently used item is evicted.
96
+ * Inserts or updates a key-value pair in the cache.
97
+ * If the key already exists, the value is updated and its frequency is incremented.
98
+ * If the cache is full, the least frequently used item is removed before inserting the new item.
63
99
*
64
- * @param key The key to insert or update .
65
- * @param value The value to insert or update .
100
+ * @param key The key associated with the value to be inserted or updated .
101
+ * @param value The value to be inserted or updated .
66
102
*/
67
103
public void put (K key , V value ) {
68
104
if (cache .containsKey (key )) {
@@ -73,7 +109,7 @@ public void put(K key, V value) {
73
109
addNodeWithUpdatedFrequency (node );
74
110
} else {
75
111
if (cache .size () >= capacity ) {
76
- cache .remove (this .head .key );
112
+ cache .remove (this .head .key ); // Evict least frequently used item
77
113
removeNode (head );
78
114
}
79
115
Node node = new Node (key , value , 1 );
@@ -84,8 +120,9 @@ public void put(K key, V value) {
84
120
85
121
/**
86
122
* Adds a node to the linked list in the correct position based on its frequency.
123
+ * The linked list is ordered by frequency, with the least frequently used node at the head.
87
124
*
88
- * @param node The node to add .
125
+ * @param node The node to be inserted into the list .
89
126
*/
90
127
private void addNodeWithUpdatedFrequency (Node node ) {
91
128
if (tail != null && head != null ) {
@@ -122,9 +159,10 @@ private void addNodeWithUpdatedFrequency(Node node) {
122
159
}
123
160
124
161
/**
125
- * Removes a node from the linked list.
162
+ * Removes a node from the doubly linked list.
163
+ * This method ensures that the pointers of neighboring nodes are properly updated.
126
164
*
127
- * @param node The node to remove .
165
+ * @param node The node to be removed from the list .
128
166
*/
129
167
private void removeNode (Node node ) {
130
168
if (node .previous != null ) {
0 commit comments