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 static final Entry REMOVED = new Entry(0,0);
|
||||||
private Object[] store;
|
private Object[] store;
|
||||||
private ProbingStrategy probingStrategy;
|
private final ProbingStrategy probingStrategy;
|
||||||
private Entry<K, V> head;
|
private Entry<K, V> head;
|
||||||
private Entry<K, V> tail;
|
private Entry<K, V> tail;
|
||||||
|
private int size;
|
||||||
|
|
||||||
public OpenAddressingHashTable(int initialCapacity, ProbingStrategy probingStrategy) {
|
public OpenAddressingHashTable(int initialCapacity, ProbingStrategy probingStrategy) {
|
||||||
this.store = new Object[initialCapacity];
|
this.store = new Object[initialCapacity];
|
||||||
this.probingStrategy = probingStrategy;
|
this.probingStrategy = probingStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public OpenAddressingHashTable(int initialCapacity)
|
||||||
|
{
|
||||||
|
this(initialCapacity, new LinearProbing());
|
||||||
|
}
|
||||||
|
|
||||||
public Optional<V> get(K key) {
|
public Optional<V> get(K key) {
|
||||||
int trial = 0;
|
int trial = 0;
|
||||||
int baseIndex = calcIndex(key, store.length);
|
int baseIndex = calcIndex(key, store.length);
|
||||||
@ -75,7 +81,8 @@ public class OpenAddressingHashTable<K, V> implements Iterable<OpenAddressingHas
|
|||||||
{
|
{
|
||||||
if (!resize)
|
if (!resize)
|
||||||
{
|
{
|
||||||
addLink(nEntry);
|
linkNewEntry(nEntry);
|
||||||
|
size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
store[index] = nEntry;
|
store[index] = nEntry;
|
||||||
@ -83,6 +90,9 @@ public class OpenAddressingHashTable<K, V> implements Iterable<OpenAddressingHas
|
|||||||
}
|
}
|
||||||
else if (entry.key.equals(nEntry.key))
|
else if (entry.key.equals(nEntry.key))
|
||||||
{
|
{
|
||||||
|
if (!resize) {
|
||||||
|
linkUpdatedEntry(entry);
|
||||||
|
}
|
||||||
entry.val = nEntry.val;
|
entry.val = nEntry.val;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -91,7 +101,7 @@ public class OpenAddressingHashTable<K, V> implements Iterable<OpenAddressingHas
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addLink(Entry<K, V> nEntry)
|
private void linkNewEntry(Entry<K, V> nEntry)
|
||||||
{
|
{
|
||||||
if (head == null)
|
if (head == null)
|
||||||
{
|
{
|
||||||
@ -105,6 +115,28 @@ public class OpenAddressingHashTable<K, V> implements Iterable<OpenAddressingHas
|
|||||||
tail = nEntry;
|
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) {
|
public void remove(K key) {
|
||||||
int trial = 0;
|
int trial = 0;
|
||||||
int baseIndex = calcIndex(key, store.length);
|
int baseIndex = calcIndex(key, store.length);
|
||||||
@ -118,15 +150,16 @@ public class OpenAddressingHashTable<K, V> implements Iterable<OpenAddressingHas
|
|||||||
}
|
}
|
||||||
else if (entry.key.equals(key))
|
else if (entry.key.equals(key))
|
||||||
{
|
{
|
||||||
removeLink(entry);
|
unlinkEntry(entry);
|
||||||
store[index] = REMOVED;
|
store[index] = REMOVED;
|
||||||
|
size--;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
trial++;
|
trial++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeLink(Entry<K, V> entry)
|
private void unlinkEntry(Entry<K, V> entry)
|
||||||
{
|
{
|
||||||
if (head == entry) {
|
if (head == entry) {
|
||||||
head = entry.next;
|
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) {
|
private int calcIndex(K key, int size) {
|
||||||
return key.hashCode() % size;
|
return key.hashCode() % size;
|
||||||
}
|
}
|
||||||
@ -183,10 +220,20 @@ public class OpenAddressingHashTable<K, V> implements Iterable<OpenAddressingHas
|
|||||||
private V val;
|
private V val;
|
||||||
private Entry<K, V> prev;
|
private Entry<K, V> prev;
|
||||||
private Entry<K, V> next;
|
private Entry<K, V> next;
|
||||||
|
|
||||||
public Entry(K key, V val) {
|
public Entry(K key, V val) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.val = val;
|
this.val = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public K key()
|
||||||
|
{
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
public V val()
|
||||||
|
{
|
||||||
|
return val;
|
||||||
|
}
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "<" + key + "," + val + ">";
|
return "<" + key + "," + val + ">";
|
||||||
}
|
}
|
||||||
@ -239,9 +286,11 @@ public class OpenAddressingHashTable<K, V> implements Iterable<OpenAddressingHas
|
|||||||
table.put("z", "zellman");
|
table.put("z", "zellman");
|
||||||
table.put("w", "walker");
|
table.put("w", "walker");
|
||||||
System.out.println(table);
|
System.out.println(table);
|
||||||
|
System.out.println(table.size());
|
||||||
|
|
||||||
table.remove("x");
|
table.remove("x");
|
||||||
table.remove("z");
|
table.remove("z");
|
||||||
|
System.out.println(table.size());
|
||||||
|
|
||||||
System.out.println(table.get("a"));
|
System.out.println(table.get("a"));
|
||||||
System.out.println(table.get("b"));
|
System.out.println(table.get("b"));
|
||||||
@ -252,6 +301,11 @@ public class OpenAddressingHashTable<K, V> implements Iterable<OpenAddressingHas
|
|||||||
table.put("z", "zebra");
|
table.put("z", "zebra");
|
||||||
System.out.println(table.get("z"));
|
System.out.println(table.get("z"));
|
||||||
System.out.println(table);
|
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("A"));
|
||||||
System.out.println(table.get("B"));
|
System.out.println(table.get("B"));
|
||||||
|
Loading…
Reference in New Issue
Block a user