/**
* Copyright (C) 2007 Rui Shen (rui.shen@gmail.com) All Right Reserved
* File : LRUCache.java
* Created : 2007-3-1
* ****************************************************************************
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 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 General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307, USA.
* *****************************************************************************
*/
package org.geometerplus.fbreader.formats.chm;
import java.util.Map;
import java.util.TreeMap;
/**
* Is it LRU?
*/
class LRUCache<K extends Comparable<K>, V> {
Map<K, Item> cacheMap = new TreeMap<K, Item>();
private int capacity;
public LRUCache(int capacity) {
if (capacity < 1)
throw new IllegalArgumentException("capacity must be positive integer");
this.capacity = capacity;
}
public synchronized V get(K key) {
Item item = cacheMap.get(key);
if (item == null)
return null;
for(Item i: cacheMap.values()) {
i.hits --;
}
item.hits += 2;
return item.value;
}
public synchronized V prune() {
if (cacheMap.size() >= capacity) {
Item kick = null;
for (Item item: cacheMap.values()) {
if (kick == null || kick.hits > item.hits) {
kick = item;
}
}
cacheMap.remove(kick.key);
return kick.value;
}
return null;
}
public synchronized void put(K key, V val) {
if (cacheMap.containsKey(key)) { // just refresh the value
cacheMap.put(key, new Item(key, val));
return;
}
prune();
cacheMap.put(key, new Item(key, val));
}
public synchronized void clear() {
cacheMap.clear();
}
public int size() {
return cacheMap.size();
}
public String toString() {
return "LRUCache " + size() + "/" + capacity + ": " + cacheMap.toString();
}
class Item {
K key;
V value;
int hits;
public Item(K key, V value) {
this.key = key;
this.value = value;
this.hits = 1;
}
public String toString() {
return "(" + hits + ")";
}
}
}