simple LRU standalone cache

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
* A simple LRU cache
*
* @author dennyliu
*
* @param
* @param
*/
public class LRUCache {

/**
* The map where the keys and values are stored in.
*/
private Map map = Collections.synchronizedMap(new HashMap());

private Node start = new Node(); // head node
private Node end = new Node(); // the last node
private int maxSize;
private final Object lockObject = new Object();

/**
* a simple linked node class
*
*/
protected static class Node {
public Node(Serializable key, Object value, long expires) {
this.key = key;
this.value = value;
this.expires = expires;
}


public Node() {
}

public Serializable key;
public Object value;
public long expires;
public Node previous;
public Node next;
}


protected void removeNode(Node node) {
synchronized (lockObject) {
node.previous.next = node.next;
node.next.previous = node.previous;
}
}


protected void insertHead(Node node) {
synchronized (lockObject) {
node.previous = start;
node.next = start.next;
start.next.previous = node;
start.next = node;
}
}


protected void moveToHead(Node node) {
synchronized (lockObject) {
node.previous.next = node.next;
node.next.previous = node.previous;
node.previous = start;
node.next = start.next;
start.next.previous = node;
start.next = node;
}
}


/**
* Constractor for LRUCache
*
* @param maxSize
* How many objects can the cache hold
*/
public LRUCache(int maxSize) {
this.maxSize = maxSize;
this.start.next = end;
this.start.previous = null;
this.end.previous = start;
this.end.next = null;
}

public static class Pair {
private K key;
private V value;


public Pair(K key, V value) {
this.key = key;
this.value = value;
}


public K getKey() {
return key;
}


public void setKey(K key) {
this.key = key;
}


public V getValue() {
return value;
}


public void setValue(V value) {
this.value = value;
}


@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Pair [key=");
builder.append(key);
builder.append(", value=");
builder.append(value);
builder.append("]");
return builder.toString();
}

}


public List> getAll() {
List> list = new ArrayList>(maxSize);
synchronized (lockObject) {
Node currentNode = start.next;
while (currentNode != end) {
list.add(new Pair(currentNode.key, currentNode.value));
currentNode = currentNode.next;
}
}
return list;
}


@SuppressWarnings("unchecked")
public V get(K key) {
Node currentNode = map.get(key);

if (currentNode == null) {
return null;
}

if (System.currentTimeMillis() > currentNode.expires) {
map.remove(currentNode.key);
removeNode(currentNode);
return null;
}

if (currentNode != start.next) {
moveToHead(currentNode);
}

return (V) currentNode.value;
}


public void put(K key, V obj) {
put(key, obj, -1);
}


public void put(K key, V value, long validTime) {
Node currentNode = map.get(key);

if (currentNode != null) {
currentNode.value = value;
if (validTime > 0) {
currentNode.expires = System.currentTimeMillis() + validTime;
}
else {
currentNode.expires = Long.MAX_VALUE;
}
moveToHead(currentNode);
return;
}

if (map.size() >= maxSize) {
// remove the last node
currentNode = end.previous;
map.remove(currentNode.key);
removeNode(currentNode);
}

long expires = 0;

if (validTime > 0) {
expires = System.currentTimeMillis() + validTime;
}
else {
expires = Long.MAX_VALUE;
}

Node node = new Node(key, value, expires);
insertHead(node);
map.put(key, node);
}


public void remove(K key) {
Node cur = map.get(key);
if (cur == null) {
return;
}
map.remove(key);
removeNode(cur);
}


public int size() {
return map.size();
}


public static void main(String[] args) {
LRUCache cache = new LRUCache(3);
cache.put("111", "111");
cache.put("222", "222");
cache.put("333", "333");
System.out.println(cache.getAll());
cache.get("111");
System.out.println(cache.getAll());
cache.put("444", "444");
System.out.println(cache.getAll());
cache.put("555", "555");
System.out.println(cache.getAll());
}
}

你可能感兴趣的:(simple LRU standalone cache)