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 <K>
* @param <V>
*/
public class LRUCache<K extends Serializable, V> {

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

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<K, V> {
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<Pair<Serializable, Object>> getAll() {
List<Pair<Serializable, Object>> list = new ArrayList<Pair<Serializable, Object>>(maxSize);
synchronized (lockObject) {
Node currentNode = start.next;
while (currentNode != end) {
list.add(new Pair<Serializable, Object>(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<String, String> cache = new LRUCache<String, String>(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());
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值