Adds LRW cache
This commit is contained in:
parent
ba1023bca1
commit
d84f4bad8d
80
src/main/java/net/abhinavsarkar/algorist/LRWCache.java
Normal file
80
src/main/java/net/abhinavsarkar/algorist/LRWCache.java
Normal file
@ -0,0 +1,80 @@
|
||||
package net.abhinavsarkar.algorist;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Optional;
|
||||
|
||||
public class LRWCache<K, V> implements Iterable<K>
|
||||
{
|
||||
|
||||
private final int capacity;
|
||||
private final OpenAddressingHashTable<K, V> store;
|
||||
|
||||
public LRWCache(int capacity) {
|
||||
this.capacity = capacity;
|
||||
this.store = new OpenAddressingHashTable<>(capacity+1);
|
||||
}
|
||||
|
||||
public Optional<V> get(K key) {
|
||||
return store.get(key);
|
||||
}
|
||||
|
||||
public void remove(K key) {
|
||||
store.remove(key);
|
||||
}
|
||||
|
||||
public void put(K key, V val) {
|
||||
store.put(key, val);
|
||||
if (store.size() > capacity) {
|
||||
store.remove(store.iterator().next().key());
|
||||
}
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
return store.size();
|
||||
}
|
||||
|
||||
public Iterator<K> iterator()
|
||||
{
|
||||
return new Iterator<K>()
|
||||
{
|
||||
private final Iterator<OpenAddressingHashTable.Entry<K,V>> it = store.iterator();
|
||||
|
||||
@Override
|
||||
public boolean hasNext()
|
||||
{
|
||||
return it.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public K next()
|
||||
{
|
||||
return it.next().key();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return store.toString();
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
LRWCache<String, String> cache = new LRWCache<>(4);
|
||||
cache.put("a", "abhinav");
|
||||
cache.put("b", "batman");
|
||||
cache.put("c", "carol");
|
||||
cache.put("z", "zellman");
|
||||
System.out.println(cache);
|
||||
|
||||
cache.put("w", "walker");
|
||||
System.out.println(cache);
|
||||
|
||||
cache.put("c", "carly");
|
||||
System.out.println(cache);
|
||||
|
||||
cache.put("x", "xander");
|
||||
System.out.println(cache);
|
||||
}
|
||||
|
||||
}
|
@ -9,15 +9,21 @@ public class OpenAddressingHashTable<K, V> implements Iterable<OpenAddressingHas
|
||||
|
||||
private static final Entry REMOVED = new Entry(0,0);
|
||||
private Object[] store;
|
||||
private ProbingStrategy probingStrategy;
|
||||
private final ProbingStrategy probingStrategy;
|
||||
private Entry<K, V> head;
|
||||
private Entry<K, V> tail;
|
||||
private int size;
|
||||
|
||||
public OpenAddressingHashTable(int initialCapacity, ProbingStrategy probingStrategy) {
|
||||
this.store = new Object[initialCapacity];
|
||||
this.probingStrategy = probingStrategy;
|
||||
}
|
||||
|
||||
public OpenAddressingHashTable(int initialCapacity)
|
||||
{
|
||||
this(initialCapacity, new LinearProbing());
|
||||
}
|
||||
|
||||
public Optional<V> get(K key) {
|
||||
int trial = 0;
|
||||
int baseIndex = calcIndex(key, store.length);
|
||||
@ -75,7 +81,8 @@ public class OpenAddressingHashTable<K, V> implements Iterable<OpenAddressingHas
|
||||
{
|
||||
if (!resize)
|
||||
{
|
||||
addLink(nEntry);
|
||||
linkNewEntry(nEntry);
|
||||
size++;
|
||||
}
|
||||
|
||||
store[index] = nEntry;
|
||||
@ -83,6 +90,9 @@ public class OpenAddressingHashTable<K, V> implements Iterable<OpenAddressingHas
|
||||
}
|
||||
else if (entry.key.equals(nEntry.key))
|
||||
{
|
||||
if (!resize) {
|
||||
linkUpdatedEntry(entry);
|
||||
}
|
||||
entry.val = nEntry.val;
|
||||
return true;
|
||||
}
|
||||
@ -91,7 +101,7 @@ public class OpenAddressingHashTable<K, V> implements Iterable<OpenAddressingHas
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addLink(Entry<K, V> nEntry)
|
||||
private void linkNewEntry(Entry<K, V> nEntry)
|
||||
{
|
||||
if (head == null)
|
||||
{
|
||||
@ -105,6 +115,28 @@ public class OpenAddressingHashTable<K, V> implements Iterable<OpenAddressingHas
|
||||
tail = nEntry;
|
||||
}
|
||||
|
||||
private void linkUpdatedEntry(Entry<K, V> entry)
|
||||
{
|
||||
if (head == null)
|
||||
{
|
||||
head = entry;
|
||||
} else if (entry == head) {
|
||||
if (entry.next != null) {
|
||||
head = entry.next;
|
||||
tail.next = entry;
|
||||
entry.prev = tail;
|
||||
tail = entry;
|
||||
}
|
||||
} else if (entry != tail) {
|
||||
entry.prev.next = entry.next;
|
||||
entry.next.prev = entry.prev;
|
||||
tail.next = entry;
|
||||
entry.prev = tail;
|
||||
entry.next = null;
|
||||
tail = entry;
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(K key) {
|
||||
int trial = 0;
|
||||
int baseIndex = calcIndex(key, store.length);
|
||||
@ -118,15 +150,16 @@ public class OpenAddressingHashTable<K, V> implements Iterable<OpenAddressingHas
|
||||
}
|
||||
else if (entry.key.equals(key))
|
||||
{
|
||||
removeLink(entry);
|
||||
unlinkEntry(entry);
|
||||
store[index] = REMOVED;
|
||||
size--;
|
||||
return;
|
||||
}
|
||||
trial++;
|
||||
}
|
||||
}
|
||||
|
||||
private void removeLink(Entry<K, V> entry)
|
||||
private void unlinkEntry(Entry<K, V> entry)
|
||||
{
|
||||
if (head == entry) {
|
||||
head = entry.next;
|
||||
@ -142,6 +175,10 @@ public class OpenAddressingHashTable<K, V> implements Iterable<OpenAddressingHas
|
||||
}
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
private int calcIndex(K key, int size) {
|
||||
return key.hashCode() % size;
|
||||
}
|
||||
@ -183,10 +220,20 @@ public class OpenAddressingHashTable<K, V> implements Iterable<OpenAddressingHas
|
||||
private V val;
|
||||
private Entry<K, V> prev;
|
||||
private Entry<K, V> next;
|
||||
|
||||
public Entry(K key, V val) {
|
||||
this.key = key;
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
public K key()
|
||||
{
|
||||
return key;
|
||||
}
|
||||
public V val()
|
||||
{
|
||||
return val;
|
||||
}
|
||||
public String toString() {
|
||||
return "<" + key + "," + val + ">";
|
||||
}
|
||||
@ -239,9 +286,11 @@ public class OpenAddressingHashTable<K, V> implements Iterable<OpenAddressingHas
|
||||
table.put("z", "zellman");
|
||||
table.put("w", "walker");
|
||||
System.out.println(table);
|
||||
System.out.println(table.size());
|
||||
|
||||
table.remove("x");
|
||||
table.remove("z");
|
||||
System.out.println(table.size());
|
||||
|
||||
System.out.println(table.get("a"));
|
||||
System.out.println(table.get("b"));
|
||||
@ -252,6 +301,11 @@ public class OpenAddressingHashTable<K, V> implements Iterable<OpenAddressingHas
|
||||
table.put("z", "zebra");
|
||||
System.out.println(table.get("z"));
|
||||
System.out.println(table);
|
||||
System.out.println(table.size());
|
||||
|
||||
table.put("w", "wanted");
|
||||
System.out.println(table);
|
||||
System.out.println(table.size());
|
||||
|
||||
System.out.println(table.get("A"));
|
||||
System.out.println(table.get("B"));
|
||||
|
Loading…
Reference in New Issue
Block a user