Skip to content

Commit 4f13178

Browse files
authored
Add LRU Cache (TheAlgorithms#2740)
1 parent 4e4f368 commit 4f13178

File tree

2 files changed

+200
-1
lines changed

2 files changed

+200
-1
lines changed

DIRECTORY.md

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
## Audio Filters
2+
## AudioFilters
33
* [IIRFilter](https://github.com/TheAlgorithms/Java/blob/master/AudioFilters/IIRFilter.java)
44

55
## Backtracking
@@ -46,11 +46,17 @@
4646
* [Bag](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Bags/Bag.java)
4747
* Buffers
4848
* [CircularBuffer](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Buffers/CircularBuffer.java)
49+
* Caches
50+
* [LRUCache](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Caches/LRUCache.java)
51+
* DisjointSets
52+
* [DisjointSets](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/DisjointSets/DisjointSets.java)
53+
* [Node](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/DisjointSets/Node.java)
4954
* DynamicArray
5055
* [DynamicArray](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/DynamicArray/DynamicArray.java)
5156
* Graphs
5257
* [A Star](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Graphs/A_Star.java)
5358
* [BellmanFord](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Graphs/BellmanFord.java)
59+
* [BipartiteGrapfDFS](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Graphs/BipartiteGrapfDFS.java)
5460
* [ConnectedComponent](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Graphs/ConnectedComponent.java)
5561
* [Cycles](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Graphs/Cycles.java)
5662
* [DIJSKSTRAS ALGORITHM](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Graphs/DIJSKSTRAS_ALGORITHM.java)
@@ -96,6 +102,7 @@
96102
* [InfixToPostfix](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Stacks/InfixToPostfix.java)
97103
* [MaximumMinimumWindow](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Stacks/MaximumMinimumWindow.java)
98104
* [NodeStack](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Stacks/NodeStack.java)
105+
* [ReverseStack](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Stacks/ReverseStack.java)
99106
* [StackArray](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Stacks/StackArray.java)
100107
* [StackArrayList](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Stacks/StackArrayList.java)
101108
* [StackOfLinkedList](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Stacks/StackOfLinkedList.java)
@@ -113,6 +120,7 @@
113120
* [LevelOrderTraversalQueue](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/LevelOrderTraversalQueue.java)
114121
* [PrintTopViewofTree](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/PrintTopViewofTree.java)
115122
* [RedBlackBST](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/RedBlackBST.java)
123+
* [SegmentTree](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/SegmentTree.java)
116124
* [TreeTraversal](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/TreeTraversal.java)
117125
* [TrieImp](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/TrieImp.java)
118126
* [ValidBSTOrNot](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/ValidBSTOrNot.java)
@@ -145,6 +153,7 @@
145153
* [LongestPalindromicSubstring](https://github.com/TheAlgorithms/Java/blob/master/DynamicProgramming/LongestPalindromicSubstring.java)
146154
* [LongestValidParentheses](https://github.com/TheAlgorithms/Java/blob/master/DynamicProgramming/LongestValidParentheses.java)
147155
* [MatrixChainMultiplication](https://github.com/TheAlgorithms/Java/blob/master/DynamicProgramming/MatrixChainMultiplication.java)
156+
* [MatrixChainRecursiveTopDownMemoisation](https://github.com/TheAlgorithms/Java/blob/master/DynamicProgramming/MatrixChainRecursiveTopDownMemoisation.java)
148157
* [MemoizationTechniqueKnapsack](https://github.com/TheAlgorithms/Java/blob/master/DynamicProgramming/MemoizationTechniqueKnapsack.java)
149158
* [MinimumPathSum](https://github.com/TheAlgorithms/Java/blob/master/DynamicProgramming/MinimumPathSum.java)
150159
* [MinimumSumPartition](https://github.com/TheAlgorithms/Java/blob/master/DynamicProgramming/MinimumSumPartition.java)
@@ -181,6 +190,7 @@
181190
* [FactorialRecursion](https://github.com/TheAlgorithms/Java/blob/master/Maths/FactorialRecursion.java)
182191
* [FFT](https://github.com/TheAlgorithms/Java/blob/master/Maths/FFT.java)
183192
* [FFTBluestein](https://github.com/TheAlgorithms/Java/blob/master/Maths/FFTBluestein.java)
193+
* [FibonacciJavaStreams](https://github.com/TheAlgorithms/Java/blob/master/Maths/FibonacciJavaStreams.java)
184194
* [FibonacciNumber](https://github.com/TheAlgorithms/Java/blob/master/Maths/FibonacciNumber.java)
185195
* [FindMax](https://github.com/TheAlgorithms/Java/blob/master/Maths/FindMax.java)
186196
* [FindMaxRecursion](https://github.com/TheAlgorithms/Java/blob/master/Maths/FindMaxRecursion.java)
@@ -216,8 +226,10 @@
216226
* [PrimeFactorization](https://github.com/TheAlgorithms/Java/blob/master/Maths/PrimeFactorization.java)
217227
* [PythagoreanTriple](https://github.com/TheAlgorithms/Java/blob/master/Maths/PythagoreanTriple.java)
218228
* [RomanNumeralUtil](https://github.com/TheAlgorithms/Java/blob/master/Maths/RomanNumeralUtil.java)
229+
* [SimpsonIntegration](https://github.com/TheAlgorithms/Java/blob/master/Maths/SimpsonIntegration.java)
219230
* [SumOfArithmeticSeries](https://github.com/TheAlgorithms/Java/blob/master/Maths/SumOfArithmeticSeries.java)
220231
* [SumOfDigits](https://github.com/TheAlgorithms/Java/blob/master/Maths/SumOfDigits.java)
232+
* [TrinomialTriangle](https://github.com/TheAlgorithms/Java/blob/master/Maths/TrinomialTriangle.java)
221233
* [VampireNumber](https://github.com/TheAlgorithms/Java/blob/master/Maths/VampireNumber.java)
222234
* [VectorCrossProduct](https://github.com/TheAlgorithms/Java/blob/master/Maths/VectorCrossProduct.java)
223235

@@ -234,6 +246,7 @@
234246
* [MedianOfRunningArray](https://github.com/TheAlgorithms/Java/blob/master/Misc/MedianOfRunningArray.java)
235247
* [PalindromePrime](https://github.com/TheAlgorithms/Java/blob/master/Misc/PalindromePrime.java)
236248
* [RangeInSortedArray](https://github.com/TheAlgorithms/Java/blob/master/Misc/RangeInSortedArray.java)
249+
* [Sparcity](https://github.com/TheAlgorithms/Java/blob/master/Misc/Sparcity.java)
237250
* [TwoSumProblem](https://github.com/TheAlgorithms/Java/blob/master/Misc/TwoSumProblem.java)
238251
* [WordBoggle](https://github.com/TheAlgorithms/Java/blob/master/Misc/WordBoggle.java)
239252

@@ -289,6 +302,7 @@
289302
## Searches
290303
* [BinarySearch](https://github.com/TheAlgorithms/Java/blob/master/Searches/BinarySearch.java)
291304
* [ExponentalSearch](https://github.com/TheAlgorithms/Java/blob/master/Searches/ExponentalSearch.java)
305+
* [FibonacciSearch](https://github.com/TheAlgorithms/Java/blob/master/Searches/FibonacciSearch.java)
292306
* [HowManyTimesRotated](https://github.com/TheAlgorithms/Java/blob/master/Searches/HowManyTimesRotated.java)
293307
* [InterpolationSearch](https://github.com/TheAlgorithms/Java/blob/master/Searches/InterpolationSearch.java)
294308
* [IterativeBinarySearch](https://github.com/TheAlgorithms/Java/blob/master/Searches/IterativeBinarySearch.java)
@@ -310,6 +324,7 @@
310324
* [BubbleSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/BubbleSort.java)
311325
* [BubbleSortRecursion](https://github.com/TheAlgorithms/Java/blob/master/Sorts/BubbleSortRecursion.java)
312326
* [BucketSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/BucketSort.java)
327+
* [CircleSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/CircleSort.java)
313328
* [CocktailShakerSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/CocktailShakerSort.java)
314329
* [CombSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/CombSort.java)
315330
* [CountingSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/CountingSort.java)
@@ -319,6 +334,7 @@
319334
* [HeapSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/HeapSort.java)
320335
* [InsertionSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/InsertionSort.java)
321336
* [MergeSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/MergeSort.java)
337+
* [MergeSortNoExtraSpace](https://github.com/TheAlgorithms/Java/blob/master/Sorts/MergeSortNoExtraSpace.java)
322338
* [MergeSortRecursive](https://github.com/TheAlgorithms/Java/blob/master/Sorts/MergeSortRecursive.java)
323339
* [PancakeSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/PancakeSort.java)
324340
* [QuickSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/QuickSort.java)
@@ -345,6 +361,7 @@
345361
* [Lower](https://github.com/TheAlgorithms/Java/blob/master/Strings/Lower.java)
346362
* [Palindrome](https://github.com/TheAlgorithms/Java/blob/master/Strings/Palindrome.java)
347363
* [Pangram](https://github.com/TheAlgorithms/Java/blob/master/Strings/Pangram.java)
364+
* [PermuteString](https://github.com/TheAlgorithms/Java/blob/master/Strings/PermuteString.java)
348365
* [ReverseString](https://github.com/TheAlgorithms/Java/blob/master/Strings/ReverseString.java)
349366
* [Rotation](https://github.com/TheAlgorithms/Java/blob/master/Strings/Rotation.java)
350367
* [Upper](https://github.com/TheAlgorithms/Java/blob/master/Strings/Upper.java)

DataStructures/Caches/LRUCache.java

+182
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
package DataStructures.Caches;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
/**
7+
* Least recently used (LRU)
8+
* <p>
9+
* Discards the least recently used items first.
10+
* This algorithm requires keeping track of what was used when,
11+
* which is expensive if one wants to make sure the algorithm always discards
12+
* the least recently used item.
13+
* https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)
14+
*
15+
* @param <K> key type
16+
* @param <V> value type
17+
*/
18+
public class LRUCache<K, V> {
19+
private final Map<K, Entry<K, V>> data = new HashMap<>();
20+
private Entry<K, V> head;
21+
private Entry<K, V> tail;
22+
private int cap;
23+
private static final int DEFAULT_CAP = 100;
24+
25+
public LRUCache() {
26+
setCapacity(DEFAULT_CAP);
27+
}
28+
29+
public LRUCache(int cap) {
30+
setCapacity(cap);
31+
}
32+
33+
private void setCapacity(int newCapacity) {
34+
checkCapacity(newCapacity);
35+
for (int i = data.size(); i > newCapacity; i--) {
36+
Entry<K, V> evicted = evict();
37+
data.remove(evicted.getKey());
38+
}
39+
this.cap = newCapacity;
40+
}
41+
42+
private Entry<K, V> evict() {
43+
if (head == null) {
44+
throw new RuntimeException("cache cannot be empty!");
45+
}
46+
Entry<K, V> evicted = head;
47+
head = evicted.getNextEntry();
48+
head.setPreEntry(null);
49+
evicted.setNextEntry(null);
50+
return evicted;
51+
}
52+
53+
private void checkCapacity(int capacity) {
54+
if (capacity <= 0) {
55+
throw new RuntimeException("capacity must greater than 0!");
56+
}
57+
}
58+
59+
public V get(K key) {
60+
if (!data.containsKey(key)) {
61+
return null;
62+
}
63+
final Entry<K, V> entry = data.get(key);
64+
moveNodeToLast(entry);
65+
return entry.getValue();
66+
}
67+
68+
private void moveNodeToLast(Entry<K, V> entry) {
69+
if (tail == entry) {
70+
return;
71+
}
72+
final Entry<K, V> preEntry = entry.getPreEntry();
73+
final Entry<K, V> nextEntry = entry.getNextEntry();
74+
if (preEntry != null) {
75+
preEntry.setNextEntry(nextEntry);
76+
}
77+
if (nextEntry != null) {
78+
nextEntry.setPreEntry(preEntry);
79+
}
80+
if (head == entry) {
81+
head = nextEntry;
82+
}
83+
tail.setNextEntry(entry);
84+
entry.setPreEntry(tail);
85+
entry.setNextEntry(null);
86+
tail = entry;
87+
}
88+
89+
public void put(K key, V value) {
90+
if (data.containsKey(key)) {
91+
final Entry<K, V> existingEntry = data.get(key);
92+
existingEntry.setValue(value);
93+
moveNodeToLast(existingEntry);
94+
return;
95+
}
96+
Entry<K, V> newEntry;
97+
if (data.size() == cap) {
98+
newEntry = evict();
99+
data.remove(newEntry.getKey());
100+
} else {
101+
newEntry = new Entry<>();
102+
}
103+
104+
newEntry.setKey(key);
105+
newEntry.setValue(value);
106+
addNewEntry(newEntry);
107+
data.put(key, newEntry);
108+
}
109+
110+
private void addNewEntry(Entry<K, V> newEntry) {
111+
if (data.isEmpty()) {
112+
head = newEntry;
113+
tail = newEntry;
114+
return;
115+
}
116+
tail.setNextEntry(newEntry);
117+
newEntry.setPreEntry(tail);
118+
newEntry.setNextEntry(null);
119+
tail = newEntry;
120+
}
121+
122+
static final class Entry<I, J> {
123+
private Entry<I, J> preEntry;
124+
private Entry<I, J> nextEntry;
125+
private I key;
126+
private J value;
127+
128+
public Entry() {
129+
}
130+
131+
public Entry(Entry<I, J> preEntry, Entry<I, J> nextEntry, I key, J value) {
132+
this.preEntry = preEntry;
133+
this.nextEntry = nextEntry;
134+
this.key = key;
135+
this.value = value;
136+
}
137+
138+
public Entry<I, J> getPreEntry() {
139+
return preEntry;
140+
}
141+
142+
public void setPreEntry(Entry<I, J> preEntry) {
143+
this.preEntry = preEntry;
144+
}
145+
146+
public Entry<I, J> getNextEntry() {
147+
return nextEntry;
148+
}
149+
150+
public void setNextEntry(Entry<I, J> nextEntry) {
151+
this.nextEntry = nextEntry;
152+
}
153+
154+
public I getKey() {
155+
return key;
156+
}
157+
158+
public void setKey(I key) {
159+
this.key = key;
160+
}
161+
162+
public J getValue() {
163+
return value;
164+
}
165+
166+
public void setValue(J value) {
167+
this.value = value;
168+
}
169+
}
170+
171+
public static void main(String[] args) {
172+
final LRUCache<String, Integer> cache = new LRUCache<>(2);
173+
cache.put("Key1", 1);
174+
cache.put("Key2", 2);
175+
cache.put("Key3", 3);
176+
cache.put("Key4", 4);
177+
System.out.println("getValue(Key1): " + cache.get("Key1"));
178+
System.out.println("getValue(Key2): " + cache.get("Key2"));
179+
System.out.println("getValue(Key3): " + cache.get("Key3"));
180+
System.out.println("getValue(Key4): " + cache.get("Key4"));
181+
}
182+
}

0 commit comments

Comments
 (0)