/*
* Copyright (c) 2008-2011 Simon Ritchie.
* All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see http://www.gnu.org/licenses/>.
*/
//package org.rimudb.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
public class LRUCache2 {
private static final float hashTableLoadFactor = 0.75f;
private LinkedHashMap map;
private int cacheSize;
/**
* Creates a new LRU cache.
*
* @param cacheSize The maximum number of entries that will be kept in this cache.
*/
public LRUCache2(int cacheSize) {
this.cacheSize = cacheSize;
int hashTableCapacity = (int) Math.ceil(cacheSize / hashTableLoadFactor) + 1;
map = new LinkedHashMap(hashTableCapacity, hashTableLoadFactor, true) {
private static final long serialVersionUID = 1;
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > LRUCache2.this.cacheSize;
}
};
}
/**
* Retrieves an entry from the cache.
* The retrieved entry is move to the head of the list as it
* is the most recently used.
*
* @param key
* @return The value associated to this key
*/
public synchronized V get(K key) {
return map.get(key);
}
/**
* Adds an entry to this cache. If the cache is full, the LRU (least
* recently used) entry is dropped.
*
* @param key
* @param value
*/
public synchronized void put(K key, V value) {
map.put(key, value);
}
/**
* Remove an entry from the cache.
*
* @param key
*/
public synchronized void remove(K key) {
map.remove(key);
}
/**
* Clears the cache.
*/
public synchronized void clear() {
map.clear();
}
/**
* Returns the number of used entries in the cache.
*
* @return the number of entries currently in the cache.
*/
public synchronized int usedEntries() {
return map.size();
}
/**
* Returns a Collection
that contains a copy of all cache
* entries.
*
* @return a Collection
with a copy of the cache content.
*/
public synchronized Collection> getAll() {
return new ArrayList>(map.entrySet());
}
public synchronized Set keySet() {
return map.keySet();
}
public int getMaximumSize() {
return cacheSize;
}
}
----------------
/*
* Copyright (c) 2008-2011 Simon Ritchie.
* All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see http://www.gnu.org/licenses/>.
*/
package org.rimudb.util;
import java.util.*;
import java.util.Map.*;
import junit.framework.*;
public class LRUCache2Tests extends TestCase {
private LRUCache2 cache = null;
public LRUCache2Tests(String name) {
super(name);
}
protected void setUp() throws Exception {
cache = new LRUCache2(5);
}
protected void tearDown() throws Exception {
super.tearDown();
}
public void testGet() {
cache.put("key1", "value1");
cache.put("key2", "value2");
cache.put("key3", "value3");
cache.put("key4", "value4");
cache.put("key5", "value5");
cache.put("key6", "value6");
assertNull(cache.get("key1"));
assertEquals("value2", cache.get("key2"));
assertEquals("value3", cache.get("key3"));
assertEquals("value4", cache.get("key4"));
assertEquals("value5", cache.get("key5"));
assertEquals("value6", cache.get("key6"));
}
public void testRemove() {
cache.put("key1", "value1");
cache.put("key2", "value2");
cache.put("key3", "value3");
cache.put("key4", "value4");
cache.put("key5", "value5");
assertEquals(5, cache.usedEntries());
cache.remove("key3");
assertEquals(4, cache.usedEntries());
}
public void testClear() {
cache.put("key1", "value1");
cache.put("key2", "value2");
cache.put("key3", "value3");
cache.put("key4", "value4");
cache.put("key5", "value5");
assertEquals(5, cache.usedEntries());
cache.clear();
assertEquals(0, cache.usedEntries());
}
public void testUsedEntries() {
cache.put("key1", "value1");
cache.put("key2", "value2");
assertEquals(2, cache.usedEntries());
cache.put("key3", "value3");
assertEquals(3, cache.usedEntries());
cache.put("key4", "value4");
cache.put("key5", "value5");
assertEquals(5, cache.usedEntries());
cache.put("key6", "value6");
assertEquals(5, cache.usedEntries());
cache.put("key7", "value7");
assertEquals(5, cache.usedEntries());
}
public void testGetAll() {
cache.put("key1", "value1");
cache.put("key2", "value2");
cache.put("key3", "value3");
cache.put("key4", "value4");
cache.put("key5", "value5");
Collection> cacheCopy = cache.getAll();
assertEquals(5, cacheCopy.size());
}
public void testKeySet() {
cache.put("key1", "value1");
cache.put("key2", "value2");
cache.put("key3", "value3");
cache.put("key4", "value4");
cache.put("key5", "value5");
Set keyset = cache.keySet();
assertTrue(keyset.contains("key1"));
assertTrue(keyset.contains("key2"));
assertTrue(keyset.contains("key3"));
assertTrue(keyset.contains("key4"));
assertTrue(keyset.contains("key5"));
}
public void testGetMaximumSize() {
assertEquals(5, cache.getMaximumSize());
cache.put("key1", "value1");
cache.put("key2", "value2");
cache.put("key3", "value3");
cache.put("key4", "value4");
cache.put("key5", "value5");
assertEquals(5, cache.getMaximumSize());
}
}