Skip to content

Commit 892a497

Browse files
authored
Merge branch 'master' into patch-2
2 parents 49d2510 + be0b1d5 commit 892a497

File tree

8 files changed

+496
-74
lines changed

8 files changed

+496
-74
lines changed

src/main/java/com/thealgorithms/datastructures/caches/LFUCache.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,21 @@
66
/**
77
* The {@code LFUCache} class implements a Least Frequently Used (LFU) cache.
88
* 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.
9+
* It maintains a mapping of keys to nodes, where each node contains the key, its associated value,
10+
* and a frequency count that tracks how many times the item has been accessed. A doubly linked list
11+
* is used to efficiently manage the ordering of items based on their usage frequency.
1112
*
12-
* @param <K> The type of keys maintained by this cache.
13-
* @param <V> The type of mapped values.
13+
* <p>This implementation is designed to provide O(1) time complexity for both the {@code get} and
14+
* {@code put} operations, which is achieved through the use of a hashmap for quick access and a
15+
* doubly linked list for maintaining the order of item frequencies.</p>
1416
*
1517
* <p>
1618
* Reference: <a href="https://en.wikipedia.org/wiki/Least_frequently_used">LFU Cache - Wikipedia</a>
1719
* </p>
1820
*
21+
* @param <K> The type of keys maintained by this cache.
22+
* @param <V> The type of mapped values.
23+
*
1924
* @author Akshay Dubey (https://github.com/itsAkshayDubey)
2025
*/
2126
public class LFUCache<K, V> {
@@ -75,7 +80,7 @@ public LFUCache(int capacity) {
7580

7681
/**
7782
* 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
83+
* If the key exists, the node's frequency is incremented, and the node is repositioned
7984
* in the linked list based on its updated frequency.
8085
*
8186
* @param key The key whose associated value is to be returned.

src/main/java/com/thealgorithms/datastructures/caches/LRUCache.java

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,40 @@
44
import java.util.Map;
55

66
/**
7-
* Least recently used (LRU)
8-
* <p>
9-
* Discards the least recently used items first. This algorithm requires keeping
10-
* track of what was used when, which is expensive if one wants to make sure the
11-
* algorithm always discards the least recently used item.
12-
* https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)
7+
* A Least Recently Used (LRU) Cache implementation.
138
*
14-
* @param <K> key type
15-
* @param <V> value type
9+
* <p>An LRU cache is a fixed-size cache that maintains items in order of use. When the cache reaches
10+
* its capacity and a new item needs to be added, it removes the least recently used item first.
11+
* This implementation provides O(1) time complexity for both get and put operations.</p>
12+
*
13+
* <p>Features:</p>
14+
* <ul>
15+
* <li>Fixed-size cache with configurable capacity</li>
16+
* <li>Constant time O(1) operations for get and put</li>
17+
* <li>Thread-unsafe - should be externally synchronized if used in concurrent environments</li>
18+
* <li>Supports null values but not null keys</li>
19+
* </ul>
20+
*
21+
* <p>Implementation Details:</p>
22+
* <ul>
23+
* <li>Uses a HashMap for O(1) key-value lookups</li>
24+
* <li>Maintains a doubly-linked list for tracking access order</li>
25+
* <li>The head of the list contains the least recently used item</li>
26+
* <li>The tail of the list contains the most recently used item</li>
27+
* </ul>
28+
*
29+
* <p>Example usage:</p>
30+
* <pre>
31+
* LRUCache<String, Integer> cache = new LRUCache<>(3); // Create cache with capacity 3
32+
* cache.put("A", 1); // Cache: A=1
33+
* cache.put("B", 2); // Cache: A=1, B=2
34+
* cache.put("C", 3); // Cache: A=1, B=2, C=3
35+
* cache.get("A"); // Cache: B=2, C=3, A=1 (A moved to end)
36+
* cache.put("D", 4); // Cache: C=3, A=1, D=4 (B evicted)
37+
* </pre>
38+
*
39+
* @param <K> the type of keys maintained by this cache
40+
* @param <V> the type of mapped values
1641
*/
1742
public class LRUCache<K, V> {
1843

@@ -30,6 +55,11 @@ public LRUCache(int cap) {
3055
setCapacity(cap);
3156
}
3257

58+
/**
59+
* Returns the current capacity of the cache.
60+
*
61+
* @param newCapacity the new capacity of the cache
62+
*/
3363
private void setCapacity(int newCapacity) {
3464
checkCapacity(newCapacity);
3565
for (int i = data.size(); i > newCapacity; i--) {
@@ -39,6 +69,11 @@ private void setCapacity(int newCapacity) {
3969
this.cap = newCapacity;
4070
}
4171

72+
/**
73+
* Evicts the least recently used item from the cache.
74+
*
75+
* @return the evicted entry
76+
*/
4277
private Entry<K, V> evict() {
4378
if (head == null) {
4479
throw new RuntimeException("cache cannot be empty!");
@@ -50,12 +85,25 @@ private Entry<K, V> evict() {
5085
return evicted;
5186
}
5287

88+
/**
89+
* Checks if the capacity is valid.
90+
*
91+
* @param capacity the capacity to check
92+
*/
5393
private void checkCapacity(int capacity) {
5494
if (capacity <= 0) {
5595
throw new RuntimeException("capacity must greater than 0!");
5696
}
5797
}
5898

99+
/**
100+
* Returns the value to which the specified key is mapped, or null if this cache contains no
101+
* mapping for the key.
102+
*
103+
* @param key the key whose associated value is to be returned
104+
* @return the value to which the specified key is mapped, or null if this cache contains no
105+
* mapping for the key
106+
*/
59107
public V get(K key) {
60108
if (!data.containsKey(key)) {
61109
return null;
@@ -65,6 +113,11 @@ public V get(K key) {
65113
return entry.getValue();
66114
}
67115

116+
/**
117+
* Moves the specified entry to the end of the list.
118+
*
119+
* @param entry the entry to move
120+
*/
68121
private void moveNodeToLast(Entry<K, V> entry) {
69122
if (tail == entry) {
70123
return;
@@ -86,6 +139,12 @@ private void moveNodeToLast(Entry<K, V> entry) {
86139
tail = entry;
87140
}
88141

142+
/**
143+
* Associates the specified value with the specified key in this cache.
144+
*
145+
* @param key the key with which the specified value is to be associated
146+
* @param value the value to be associated with the specified key
147+
*/
89148
public void put(K key, V value) {
90149
if (data.containsKey(key)) {
91150
final Entry<K, V> existingEntry = data.get(key);
@@ -107,6 +166,11 @@ public void put(K key, V value) {
107166
data.put(key, newEntry);
108167
}
109168

169+
/**
170+
* Adds a new entry to the end of the list.
171+
*
172+
* @param newEntry the entry to add
173+
*/
110174
private void addNewEntry(Entry<K, V> newEntry) {
111175
if (data.isEmpty()) {
112176
head = newEntry;

0 commit comments

Comments
 (0)