44import 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 */
1742public 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