Add MRU Cache (#2738)
This commit is contained in:
parent
0ab11140b5
commit
6934c53c04
@ -3,6 +3,7 @@
|
|||||||
* [IIRFilter](https://github.com/TheAlgorithms/Java/blob/master/AudioFilters/IIRFilter.java)
|
* [IIRFilter](https://github.com/TheAlgorithms/Java/blob/master/AudioFilters/IIRFilter.java)
|
||||||
|
|
||||||
## Backtracking
|
## Backtracking
|
||||||
|
* [KnightsTour](https://github.com/TheAlgorithms/Java/blob/master/Backtracking/KnightsTour.java)
|
||||||
* [NQueens](https://github.com/TheAlgorithms/Java/blob/master/Backtracking/NQueens.java)
|
* [NQueens](https://github.com/TheAlgorithms/Java/blob/master/Backtracking/NQueens.java)
|
||||||
* [PowerSum](https://github.com/TheAlgorithms/Java/blob/master/Backtracking/PowerSum.java)
|
* [PowerSum](https://github.com/TheAlgorithms/Java/blob/master/Backtracking/PowerSum.java)
|
||||||
|
|
||||||
@ -48,6 +49,7 @@
|
|||||||
* [CircularBuffer](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Buffers/CircularBuffer.java)
|
* [CircularBuffer](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Buffers/CircularBuffer.java)
|
||||||
* Caches
|
* Caches
|
||||||
* [LRUCache](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Caches/LRUCache.java)
|
* [LRUCache](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Caches/LRUCache.java)
|
||||||
|
* [MRUCache](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Caches/MRUCache.java)
|
||||||
* DisjointSets
|
* DisjointSets
|
||||||
* [DisjointSets](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/DisjointSets/DisjointSets.java)
|
* [DisjointSets](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/DisjointSets/DisjointSets.java)
|
||||||
* [Node](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/DisjointSets/Node.java)
|
* [Node](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/DisjointSets/Node.java)
|
||||||
@ -82,6 +84,7 @@
|
|||||||
* Lists
|
* Lists
|
||||||
* [CircleLinkedList](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Lists/CircleLinkedList.java)
|
* [CircleLinkedList](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Lists/CircleLinkedList.java)
|
||||||
* [CountSinglyLinkedListRecursion](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Lists/CountSinglyLinkedListRecursion.java)
|
* [CountSinglyLinkedListRecursion](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Lists/CountSinglyLinkedListRecursion.java)
|
||||||
|
* [CreateAndDetectLoop](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Lists/CreateAndDetectLoop.java)
|
||||||
* [CursorLinkedList](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Lists/CursorLinkedList.java)
|
* [CursorLinkedList](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Lists/CursorLinkedList.java)
|
||||||
* [DoublyLinkedList](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Lists/DoublyLinkedList.java)
|
* [DoublyLinkedList](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Lists/DoublyLinkedList.java)
|
||||||
* [Merge K SortedLinkedlist](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Lists/Merge_K_SortedLinkedlist.java)
|
* [Merge K SortedLinkedlist](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Lists/Merge_K_SortedLinkedlist.java)
|
||||||
@ -113,11 +116,14 @@
|
|||||||
* [BSTRecursive](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/BSTRecursive.java)
|
* [BSTRecursive](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/BSTRecursive.java)
|
||||||
* [BSTRecursiveGeneric](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/BSTRecursiveGeneric.java)
|
* [BSTRecursiveGeneric](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/BSTRecursiveGeneric.java)
|
||||||
* [CeilInBinarySearchTree](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/CeilInBinarySearchTree.java)
|
* [CeilInBinarySearchTree](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/CeilInBinarySearchTree.java)
|
||||||
|
* [CreateBinaryTreeFromInorderPreorder](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/CreateBinaryTreeFromInorderPreorder.java)
|
||||||
|
* [CreateBSTFromSortedArray](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/CreateBSTFromSortedArray.java)
|
||||||
* [FenwickTree](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/FenwickTree.java)
|
* [FenwickTree](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/FenwickTree.java)
|
||||||
* [GenericTree](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/GenericTree.java)
|
* [GenericTree](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/GenericTree.java)
|
||||||
* [LCA](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/LCA.java)
|
* [LCA](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/LCA.java)
|
||||||
* [LevelOrderTraversal](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/LevelOrderTraversal.java)
|
* [LevelOrderTraversal](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/LevelOrderTraversal.java)
|
||||||
* [LevelOrderTraversalQueue](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/LevelOrderTraversalQueue.java)
|
* [LevelOrderTraversalQueue](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/LevelOrderTraversalQueue.java)
|
||||||
|
* [nearestRightKey](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/nearestRightKey.java)
|
||||||
* [PrintTopViewofTree](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/PrintTopViewofTree.java)
|
* [PrintTopViewofTree](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/PrintTopViewofTree.java)
|
||||||
* [RedBlackBST](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/RedBlackBST.java)
|
* [RedBlackBST](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/RedBlackBST.java)
|
||||||
* [SegmentTree](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/SegmentTree.java)
|
* [SegmentTree](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/SegmentTree.java)
|
||||||
@ -253,6 +259,7 @@
|
|||||||
## Others
|
## Others
|
||||||
* [BestFit](https://github.com/TheAlgorithms/Java/blob/master/Others/BestFit.java)
|
* [BestFit](https://github.com/TheAlgorithms/Java/blob/master/Others/BestFit.java)
|
||||||
* [BFPRT](https://github.com/TheAlgorithms/Java/blob/master/Others/BFPRT.java)
|
* [BFPRT](https://github.com/TheAlgorithms/Java/blob/master/Others/BFPRT.java)
|
||||||
|
* [BoyerMoore](https://github.com/TheAlgorithms/Java/blob/master/Others/BoyerMoore.java)
|
||||||
* [BrianKernighanAlgorithm](https://github.com/TheAlgorithms/Java/blob/master/Others/BrianKernighanAlgorithm.java)
|
* [BrianKernighanAlgorithm](https://github.com/TheAlgorithms/Java/blob/master/Others/BrianKernighanAlgorithm.java)
|
||||||
* [CountChar](https://github.com/TheAlgorithms/Java/blob/master/Others/CountChar.java)
|
* [CountChar](https://github.com/TheAlgorithms/Java/blob/master/Others/CountChar.java)
|
||||||
* [CountWords](https://github.com/TheAlgorithms/Java/blob/master/Others/CountWords.java)
|
* [CountWords](https://github.com/TheAlgorithms/Java/blob/master/Others/CountWords.java)
|
||||||
@ -317,6 +324,7 @@
|
|||||||
* [SquareRootBinarySearch](https://github.com/TheAlgorithms/Java/blob/master/Searches/SquareRootBinarySearch.java)
|
* [SquareRootBinarySearch](https://github.com/TheAlgorithms/Java/blob/master/Searches/SquareRootBinarySearch.java)
|
||||||
* [TernarySearch](https://github.com/TheAlgorithms/Java/blob/master/Searches/TernarySearch.java)
|
* [TernarySearch](https://github.com/TheAlgorithms/Java/blob/master/Searches/TernarySearch.java)
|
||||||
* [UnionFind](https://github.com/TheAlgorithms/Java/blob/master/Searches/UnionFind.java)
|
* [UnionFind](https://github.com/TheAlgorithms/Java/blob/master/Searches/UnionFind.java)
|
||||||
|
* [UpperBound](https://github.com/TheAlgorithms/Java/blob/master/Searches/UpperBound.java)
|
||||||
|
|
||||||
## Sorts
|
## Sorts
|
||||||
* [BitonicSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/BitonicSort.java)
|
* [BitonicSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/BitonicSort.java)
|
||||||
|
179
DataStructures/Caches/MRUCache.java
Normal file
179
DataStructures/Caches/MRUCache.java
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
package DataStructures.Caches;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Most recently used (MRU)
|
||||||
|
* <p>
|
||||||
|
* In contrast to Least Recently Used (LRU), MRU discards the most recently used items first.
|
||||||
|
* https://en.wikipedia.org/wiki/Cache_replacement_policies#Most_recently_used_(MRU)
|
||||||
|
*
|
||||||
|
* @param <K> key type
|
||||||
|
* @param <V> value type
|
||||||
|
*/
|
||||||
|
public class MRUCache<K, V> {
|
||||||
|
private final Map<K, Entry<K, V>> data = new HashMap<>();
|
||||||
|
private Entry<K, V> head;
|
||||||
|
private Entry<K, V> tail;
|
||||||
|
private int cap;
|
||||||
|
private static final int DEFAULT_CAP = 100;
|
||||||
|
|
||||||
|
public MRUCache() {
|
||||||
|
setCapacity(DEFAULT_CAP);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setCapacity(int newCapacity) {
|
||||||
|
checkCapacity(newCapacity);
|
||||||
|
for (int i = data.size(); i > newCapacity; i--) {
|
||||||
|
Entry<K, V> evicted = evict();
|
||||||
|
data.remove(evicted.getKey());
|
||||||
|
}
|
||||||
|
this.cap = newCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void checkCapacity(int capacity) {
|
||||||
|
if (capacity <= 0) {
|
||||||
|
throw new RuntimeException("capacity must greater than 0!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Entry<K, V> evict() {
|
||||||
|
if (head == null) {
|
||||||
|
throw new RuntimeException("cache cannot be empty!");
|
||||||
|
}
|
||||||
|
final Entry<K, V> evicted = this.tail;
|
||||||
|
tail = evicted.getPreEntry();
|
||||||
|
tail.setNextEntry(null);
|
||||||
|
evicted.setNextEntry(null);
|
||||||
|
return evicted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MRUCache(int cap) {
|
||||||
|
setCapacity(cap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public V get(K key) {
|
||||||
|
if (!data.containsKey(key)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final Entry<K, V> entry = data.get(key);
|
||||||
|
moveEntryToLast(entry);
|
||||||
|
return entry.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(K key, V value) {
|
||||||
|
if (data.containsKey(key)) {
|
||||||
|
final Entry<K, V> exitingEntry = data.get(key);
|
||||||
|
exitingEntry.setValue(value);
|
||||||
|
moveEntryToLast(exitingEntry);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Entry<K, V> newEntry;
|
||||||
|
if (data.size() == cap) {
|
||||||
|
newEntry = evict();
|
||||||
|
data.remove(newEntry.getKey());
|
||||||
|
} else {
|
||||||
|
newEntry = new Entry<>();
|
||||||
|
}
|
||||||
|
newEntry.setKey(key);
|
||||||
|
newEntry.setValue(value);
|
||||||
|
addNewEntry(newEntry);
|
||||||
|
data.put(key, newEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addNewEntry(Entry<K, V> newEntry) {
|
||||||
|
if (data.isEmpty()) {
|
||||||
|
head = newEntry;
|
||||||
|
tail = newEntry;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tail.setNextEntry(newEntry);
|
||||||
|
newEntry.setPreEntry(tail);
|
||||||
|
newEntry.setNextEntry(null);
|
||||||
|
tail = newEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void moveEntryToLast(Entry<K, V> entry) {
|
||||||
|
if (tail == entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final Entry<K, V> preEntry = entry.getPreEntry();
|
||||||
|
final Entry<K, V> nextEntry = entry.getNextEntry();
|
||||||
|
if (preEntry != null) {
|
||||||
|
preEntry.setNextEntry(nextEntry);
|
||||||
|
}
|
||||||
|
if (nextEntry != null) {
|
||||||
|
nextEntry.setPreEntry(preEntry);
|
||||||
|
}
|
||||||
|
if (head == entry) {
|
||||||
|
head = nextEntry;
|
||||||
|
}
|
||||||
|
tail.setNextEntry(entry);
|
||||||
|
entry.setPreEntry(tail);
|
||||||
|
entry.setNextEntry(null);
|
||||||
|
tail = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class Entry<I, J> {
|
||||||
|
private Entry<I, J> preEntry;
|
||||||
|
private Entry<I, J> nextEntry;
|
||||||
|
private I key;
|
||||||
|
private J value;
|
||||||
|
|
||||||
|
public Entry() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Entry(Entry<I, J> preEntry, Entry<I, J> nextEntry, I key, J value) {
|
||||||
|
this.preEntry = preEntry;
|
||||||
|
this.nextEntry = nextEntry;
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Entry<I, J> getPreEntry() {
|
||||||
|
return preEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPreEntry(Entry<I, J> preEntry) {
|
||||||
|
this.preEntry = preEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Entry<I, J> getNextEntry() {
|
||||||
|
return nextEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNextEntry(Entry<I, J> nextEntry) {
|
||||||
|
this.nextEntry = nextEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public I getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(I key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public J getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(J value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
final MRUCache<String, Integer> cache = new MRUCache<>(2);
|
||||||
|
cache.put("Key1", 1);
|
||||||
|
cache.put("Key2", 2);
|
||||||
|
cache.put("Key3", 3);
|
||||||
|
cache.put("Key4", 4);
|
||||||
|
System.out.println("getValue(Key1): " + cache.get("Key1"));
|
||||||
|
System.out.println("getValue(Key2): " + cache.get("Key2"));
|
||||||
|
System.out.println("getValue(Key3): " + cache.get("Key3"));
|
||||||
|
System.out.println("getValue(Key4): " + cache.get("Key4"));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user