Skip to content

Commit fcd343b

Browse files
committed
LFU and LRU strategy
0 parents  commit fcd343b

15 files changed

+289
-0
lines changed

.gitignore

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
### IntelliJ IDEA ###
2+
out/
3+
!**/src/main/**/out/
4+
!**/src/test/**/out/
5+
6+
### Eclipse ###
7+
.apt_generated
8+
.classpath
9+
.factorypath
10+
.project
11+
.settings
12+
.springBeans
13+
.sts4-cache
14+
bin/
15+
!**/src/main/**/bin/
16+
!**/src/test/**/bin/
17+
18+
### NetBeans ###
19+
/nbproject/private/
20+
/nbbuild/
21+
/dist/
22+
/nbdist/
23+
/.nb-gradle/
24+
25+
### VS Code ###
26+
.vscode/
27+
28+
### Mac OS ###
29+
.DS_Store

.idea/.gitignore

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/misc.xml

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/modules.xml

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/vcs.xml

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

GenericCache.iml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<module type="JAVA_MODULE" version="4">
3+
<component name="NewModuleRootManager" inherit-compiler-output="true">
4+
<exclude-output />
5+
<content url="file://$MODULE_DIR$">
6+
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
7+
</content>
8+
<orderEntry type="inheritedJdk" />
9+
<orderEntry type="sourceFolder" forTests="false" />
10+
</component>
11+
</module>

src/GenericCache.java

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import evictionpolicy.EvictionPolicy;
2+
import evictionpolicy.EvictionPolicyFactory;
3+
4+
import java.util.HashMap;
5+
import java.util.Map;
6+
7+
public class GenericCache<T> {
8+
int capacity;
9+
Map<String, T> store = new HashMap<>();
10+
EvictionPolicy policy;
11+
12+
GenericCache(int capacity, EvictionPolicy policy) {
13+
this.capacity = capacity;
14+
this.policy = policy;
15+
}
16+
17+
public T get(String key) throws KeyNotFoundException {
18+
if (!store.containsKey(key)) {
19+
throw new KeyNotFoundException();
20+
}
21+
policy.recordKeyAcccess(key);
22+
return store.get(key);
23+
}
24+
25+
public void put(String key, T value) {
26+
if (!store.containsKey(key) && store.size() == capacity) {
27+
String toEvict = policy.pollKeyToEvict();
28+
store.remove(toEvict);
29+
}
30+
policy.recordKeyAcccess(key);
31+
store.put(key, value);
32+
}
33+
}

src/KeyNotFoundException.java

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
public class KeyNotFoundException extends Exception {
2+
}

src/LList/LLNode.java

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package LList;
2+
3+
public class LLNode {
4+
public String val;
5+
public LLNode prev, next;
6+
7+
public LLNode(String val, LLNode prev, LLNode next) {
8+
this.val = val;
9+
this.next = next;
10+
this.prev = prev;
11+
}
12+
}

src/LList/LList.java

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package LList;
2+
3+
public class LList {
4+
LLNode root = new LLNode("root", null, null);
5+
LLNode curr = root;
6+
7+
// Adds a val to the end;
8+
public LLNode add(String val) {
9+
curr.next = new LLNode(val, curr, null);
10+
curr = curr.next;
11+
return curr;
12+
}
13+
14+
public void remove(LLNode todel) {
15+
assert todel != root;
16+
LLNode before = todel.prev;
17+
LLNode after = todel.next;
18+
before.next = after;
19+
if (after != null) {
20+
after.prev = before;
21+
}
22+
if (curr == todel) {
23+
curr = before;
24+
}
25+
todel.prev = null;
26+
todel.next = null;
27+
}
28+
29+
public LLNode pollFirst() {
30+
assert curr != root;
31+
LLNode temp = root.next;
32+
remove(temp);
33+
return temp;
34+
}
35+
36+
public void debugLL() {
37+
LLNode itr = root;
38+
while (itr != null) {
39+
System.out.print(itr.val + " => ");
40+
itr = itr.next;
41+
}
42+
System.out.println("");
43+
}
44+
}

src/Main.java

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import evictionpolicy.EvictionPolicyFactory;
2+
3+
public class Main {
4+
static GenericCache cache;
5+
6+
public static void main(String[] args) {
7+
cache = new GenericCache<Long>(3, EvictionPolicyFactory.getLFU());
8+
9+
attemptGet("k1");
10+
recordAndSet("k1", 32L);
11+
attemptGet("k1");
12+
recordAndSet("k2", 33L);
13+
recordAndSet("k2", 33L);
14+
recordAndSet("k3", 34L);
15+
recordAndSet("k1", 35L);
16+
recordAndSet("k4", 33L);
17+
recordAndSet("k5", 35L);
18+
attemptGet("k4");
19+
attemptGet("k1");
20+
attemptGet("k2");
21+
}
22+
23+
// prints key and value if key is found, otherwise prints "not found"
24+
public static void attemptGet(String key) {
25+
try {
26+
Long val = (Long) cache.get(key);
27+
System.out.println(key + " : " + val);
28+
} catch (KeyNotFoundException k) {
29+
System.out.println("not found: " + key);
30+
}
31+
}
32+
33+
public static void recordAndSet(String key, Long val) {
34+
System.out.println("setting: " + key + " : " + val);
35+
cache.put(key, val);
36+
}
37+
}
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package evictionpolicy;
2+
3+
public interface EvictionPolicy {
4+
public void recordKeyAcccess(String key);
5+
6+
public String pollKeyToEvict();
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package evictionpolicy;
2+
3+
public class EvictionPolicyFactory {
4+
public static EvictionPolicy getLRU() {
5+
return new LRUEvictionPolicy();
6+
}
7+
8+
public static EvictionPolicy getLFU() {
9+
return new LFUEvictionPolicy();
10+
}
11+
}
+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package evictionpolicy;
2+
3+
import java.util.Iterator;
4+
import java.util.Map;
5+
import java.util.TreeMap;
6+
import java.lang.Integer;
7+
import java.util.TreeSet;
8+
9+
public class LFUEvictionPolicy implements EvictionPolicy {
10+
11+
private static class Pair implements Comparable<Pair> {
12+
String key;
13+
Integer count;
14+
15+
Pair(String key, Integer count) {
16+
this.key = key;
17+
this.count = count;
18+
}
19+
20+
@Override
21+
public int compareTo(Pair o) {
22+
if (count.compareTo(o.count) == 0) {
23+
return key.compareTo(o.key);
24+
}
25+
return count.compareTo(o.count);
26+
}
27+
}
28+
29+
Map<String, Integer> keyToCount = new TreeMap<>();
30+
TreeSet<Pair> keyAndCount = new TreeSet<>();
31+
32+
@Override
33+
public void recordKeyAcccess(String key) {
34+
Integer count = 0;
35+
if (keyToCount.containsKey(key)) {
36+
count = keyToCount.get(key);
37+
38+
keyToCount.remove(key);
39+
keyAndCount.remove(new Pair(key, count));
40+
}
41+
42+
keyToCount.put(key, count + 1);
43+
keyAndCount.add(new Pair(key, count + 1));
44+
}
45+
46+
@Override
47+
public String pollKeyToEvict() {
48+
Pair toEvict = keyAndCount.first();
49+
keyToCount.remove(toEvict.key);
50+
keyAndCount.remove(toEvict);
51+
return toEvict.key;
52+
}
53+
}
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package evictionpolicy;
2+
3+
import LList.LLNode;
4+
import LList.LList;
5+
6+
import java.util.HashMap;
7+
import java.util.Map;
8+
9+
public class LRUEvictionPolicy implements EvictionPolicy {
10+
Map<String, LLNode> keyToSequence = new HashMap<>();
11+
LList sequence = new LList();
12+
13+
@Override
14+
public void recordKeyAcccess(String key) {
15+
if (keyToSequence.containsKey(key)) {
16+
LLNode toRemove = keyToSequence.get(key);
17+
keyToSequence.remove(key);
18+
sequence.remove(toRemove);
19+
}
20+
keyToSequence.put(key, sequence.add(key));
21+
}
22+
23+
@Override
24+
public String pollKeyToEvict() {
25+
return sequence.pollFirst().val;
26+
}
27+
}

0 commit comments

Comments
 (0)