2011-05-10 99 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