44import java .util .Map ;
55
66/**
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+ *
819 * @author Akshay Dubey (https://github.com/itsAkshayDubey)
920 */
1021public class LFUCache <K , V > {
1122
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+ */
1228 private class Node {
1329 private final K key ;
1430 private V value ;
1531 private int frequency ;
1632 private Node previous ;
1733 private Node next ;
1834
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+ */
1942 Node (K key , V value , int frequency ) {
2043 this .key = key ;
2144 this .value = value ;
@@ -29,10 +52,19 @@ private class Node {
2952 private final int capacity ;
3053 private static final int DEFAULT_CAPACITY = 100 ;
3154
55+ /**
56+ * Constructs an LFU cache with the default capacity.
57+ */
3258 public LFUCache () {
3359 this (DEFAULT_CAPACITY );
3460 }
3561
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+ */
3668 public LFUCache (int capacity ) {
3769 if (capacity <= 0 ) {
3870 throw new IllegalArgumentException ("Capacity must be greater than zero." );
@@ -42,10 +74,12 @@ public LFUCache(int capacity) {
4274 }
4375
4476 /**
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.
4680 *
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 .
4983 */
5084 public V get (K key ) {
5185 Node node = cache .get (key );
@@ -59,10 +93,12 @@ public V get(K key) {
5993 }
6094
6195 /**
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.
6399 *
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 .
66102 */
67103 public void put (K key , V value ) {
68104 if (cache .containsKey (key )) {
@@ -73,7 +109,7 @@ public void put(K key, V value) {
73109 addNodeWithUpdatedFrequency (node );
74110 } else {
75111 if (cache .size () >= capacity ) {
76- cache .remove (this .head .key );
112+ cache .remove (this .head .key ); // Evict least frequently used item
77113 removeNode (head );
78114 }
79115 Node node = new Node (key , value , 1 );
@@ -84,8 +120,9 @@ public void put(K key, V value) {
84120
85121 /**
86122 * 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.
87124 *
88- * @param node The node to add .
125+ * @param node The node to be inserted into the list .
89126 */
90127 private void addNodeWithUpdatedFrequency (Node node ) {
91128 if (tail != null && head != null ) {
@@ -122,9 +159,10 @@ private void addNodeWithUpdatedFrequency(Node node) {
122159 }
123160
124161 /**
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.
126164 *
127- * @param node The node to remove .
165+ * @param node The node to be removed from the list .
128166 */
129167 private void removeNode (Node node ) {
130168 if (node .previous != null ) {
0 commit comments