2011-05-10 100 views
2

我试图缓存许多类似的值只有类集要求。不幸的是Set<?>只允许我检查里面是否存在元素 - 它不会将现有元素给我。我想要做的是:缓存集合样集合

Element e = receiveSomeElement(); 
e = elements.cache(e); 
// now e is either the original e, or one that was already in the cache 
doSomeWorkOn(e); 

我大概可以模拟与SortedSet并获得.subSet(e, e),但似乎时间保持排序的集浪费。我也可以使用HashMap<Element, Element>并存储相同的引用作为键和值,但这似乎就像脏......

有没有更好的方法来做到这一点?

+0

只有HashMap中去,只有你可以实现缓存 – developer 2011-05-10 10:23:17

+0

方式你为什么要这么做?你什么时候从缓存中清除元素?你想怎么做?您可能需要考虑在缓存中使用WeakReferences。 – Kaj 2011-05-10 10:29:34

+0

我最后写'ObjectCache 实现集'用'WeakHashMap中>'成员。 – viraptor 2011-05-10 10:59:51

回答

3

如果您使用的是HashSet,底层实现实际上使用HashMap,所以我建议您使用HashMap。下面

0

你可能想使用LinkedHashMap中,所以你可以实现一个简单的驱逐策略。

Map<Element, Element> cache = new LinkedHashMap<Element, Element>(16, 0.7, true){ 
    protected boolean removeEldestEntry(Map.Entry<Element, Element> eldest) { 
     return size() > MAX_SIZE; 
    } 

    public Element get(Object key) { 
     Element element = super.get(key); 
     // put if not present. 
     if (element == null) { 
      element = (Element) key; 
      super.put(element, element) 
     } 
     return element; 
    } 
}; 

这样你就可以调用get(E),如果它不存在,它会返回e的。通过根据需要删除最近最少使用的条目,将其限制为MAX_SIZE。

0

这是一个解决方案。不要求我会像这样解决它。将其看作是如何获取一组中特定元素的演示。

// Create a temporary copy of the cache. 
Set<Element> matches = new HashSet<Element>(cache); 

// Remove all elements that don't equal the soughtElement. 
matches.retainAll(Collections.singleton(soughtElement)); 

if (matches.isEmpty()) { 
    // ... not found 
} else { 
    Element found = matches.iterator().next(); 
    // ... 
} 
+0

这看起来像每一个高速缓存()调用,如果你有一组10K +元素... – viraptor 2011-05-10 10:56:45

+0

是的很多复制。一个'O(n)'解决方案,当你用'O(1)'离开时可以使用map:P – aioobe 2011-05-10 11:26:21

1

您可能想看看Apache Collections提供的LRUMap。它的行为像一个Map,但限制了大小,以便在处理大量数据时不会失去动手。我也写了一篇关于如何添加一些簿记围绕LRUMap做的时候不使用它也缩小了一篇文章:Blog post: Caching without Crashing