【问题标题】:Caching set-like collection缓存类集合
【发布时间】:2011-05-10 10:19:06
【问题描述】:

我正在尝试缓存许多仅具有类似集合要求的类似值。不幸的是,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> 并存储与键和值相同的引用,但这似乎同样肮脏......

有更好的方法吗?

【问题讨论】:

  • 只使用 hashmap,这是实现缓存的唯一方法
  • 为什么要这样做?什么时候从缓存中清除元素?你想怎么做?您可能需要考虑在缓存中使用 Wea​​kReferences。
  • 我最终写了ObjectCache<E> implements Set<E>WeakHashMap<E, WeakReference<E>> 成员。

标签: java caching collections set


【解决方案1】:

如果你使用的是 HashSet,那么底层实现实际上还是使用了 HashMap,所以我建议你使用 HashMap。

【讨论】:

    【解决方案2】:

    您可能想看看 Apache Collections 提供的 LRUMap。它的行为类似于地图,但限制了大小,以便在处理大量数据时不会失控。我还写了一篇关于如何在 LRUMap 周围添加一些簿记以使其在不使用时也缩小的文章:Blog post: Caching without Crashing

    【讨论】:

      【解决方案3】:

      下面是这里的基本缓存实现,也使用了 HashMap Caching implementation

      【讨论】:

        【解决方案4】:

        您可能希望使用 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。

        【讨论】:

          【解决方案5】:

          这里有一个解决方案。没有声称我会这样解决它。将其视为如何获取集合中特定元素的演示。

          // 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();
              // ...
          }
          

          【讨论】:

          • 如果集合中有 10k+ 个元素,那么每次调用 cache() 时都会进行大量复制...
          • 是的。 O(n) 解决方案,当您可以使用地图摆脱 O(1) 时:P
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-06-20
          • 2014-03-13
          • 1970-01-01
          • 2012-02-17
          • 2014-08-02
          • 2017-01-03
          • 1970-01-01
          相关资源
          最近更新 更多