我有一个java应用程序,它提供大平铺图像的重采样区域。
由于连续区域查询通常彼此接近,因此将图像切片缓存在哈希映射中是有意义的。现在我想让这个缓存无限期地增长。
为了不失去性能,我需要一种O(1)/ O(logN)方法来查找最长时间未被访问的地图元素。有没有办法做到这一点,它与仅从缓存中删除随机元素相比如何?
堆或bst允许我保持对最后一次访问的列表进行排序,但更新其中一次访问的最后一次访问将需要线性时间。
以下是我目前使用的代码的摘录:
insertBefore()
这不是最佳选择,因为最久前加载的图像可能刚刚被访问过。
答案 0 :(得分:1)
LinkedHashMap与Collections.synchronizedMap(linkedHashMap)
一起完成了这个伎俩。 LinkedHashMap的removeEldestEntry方法允许定义何时删除最后访问的条目的条件。
final int MAX_BUF_SIZE = 1000;
Map<Point, BufferedImage> loadedImages = new LinkedHashMap(MAX_BUF_SIZE + 1, .75F, true) {
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > MAX_BUF_SIZE;
}
};
int getRGB(double tileX, double tileY) {
Point point = new Point((int) tileX, (int) tileY);
if (!loadedImages.containsKey(point)) {
loadedImages.put(point, ImageIO.read(new File("R:\\tiles\\22\\" + point.y + "_" + point.x + ".jpg")));
}
BufferedImage img = loadedImages.get(point);
//do stuff with img..
}
答案 1 :(得分:0)
将LinkedHashMap用作LRUCache - 简单示例:
public class LRULinkedHashMap extends LinkedHashMap<Integer, String> {
/**
*
*/
private static final long serialVersionUID = 1L;
private int capacity;
public LRULinkedHashMap(int capacity) {
// initialise the capacity, and when to 'double' the capacity (75% of capacity) and
// 'true' if the ordering should be done based on the last
// access (from least-recently accessed to most-recently accessed)
super(capacity, 0.75f, true);
this.capacity = capacity;
}
/**
* Returns true if this map should remove its eldest entry.
* This method is invoked by put and putAll after inserting a new entry into the map.
* It provides the implementor with the opportunity to remove the eldest entry each
* time a new one is added. This is useful if the map represents a cache: it allows
* the map to reduce memory consumption by deleting stale entries.
*/
@Override
protected boolean removeEldestEntry(Entry<Integer, String> eldest) {
// this will return true and remove the eldest entry every time the size of the map
// is bigger than the capacity - the size() will never go beyond double the capacity
// (it will double automatically when it hits 75% of original capacity) as this ensures
// any 'put' entry over the capacity is removes the eldest object
return size() > this.capacity;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
// Last Recently Used LinkedHashMap Cache
LRULinkedHashMap cache = new LRULinkedHashMap(6);
// put some objects into the map
cache.put(1, "one");
System.out.println(cache);
cache.put(2, "two");
System.out.println(cache);
cache.put(3, "three");
System.out.println(cache);
cache.put(4, "four");
System.out.println(cache);
cache.put(5, "five");
System.out.println(cache);
cache.put(6, "six"); // capacity (6) reached
System.out.println(cache + " <-- Capacity Reached");
cache.put(7, "seven"); // 1 is removed - eldest
System.out.println(cache + " <-- 1 removed");
cache.put(8, "eight"); // 2 is removed - next eldest
// access an object before it is removed
System.out.println(cache + " <-- 2 Removed");
cache.get(4); // 4 retrieved placed after 8 - nothing removed (we've only changed the order, not put anything into the map)
System.out.println(cache + " <-- '4' Retrieved, access order changed only");
cache.put(9, "nine"); // 3 is removed - next eldest (4 was retrieved!)
System.out.println(cache + " <-- 3 Removed");
cache.put(10, "ten"); // 5 removed - next eldest
// first item is always the eldest - will be next to go if item retrieved or put in map
System.out.println(cache + " <-- 5 Removed");
}
}