一尘不染

寻找替代java.util.Map的替代品

java

问题

在解决这个问题之后,似乎基于文件或磁盘的Map实现可能是解决我在此处提到的问题的正确解决方案。精简版:

  • 目前,我已将Map实施为ConcurrentHashMap
  • 条目以相当固定的速率连续添加到其中。稍后对此进行详细说明。
  • 最终,无论如何,这意味着JVM耗尽了堆空间。

在工作中,(强烈)建议我使用SQLite解决此问题,但是在问了上一个问题之后,我认为数据库不是适合此工作的合适工具。所以- 让我知道这听起来是否疯狂
-我认为更好的解决方案是将其Map存储在磁盘上。

坏主意:自己实施。更好的主意:使用别人的图书馆! 哪一个?

要求

必须具备的:

  • 自由。
  • 坚持不懈 在JVM重新启动之间,数据需要保留。
  • 某种 可搜索性。 是的,我需要能够检索并删除这些织补数据。基本结果集过滤为佳。
  • 与平台无关。 需要在Windows或Linux机器上可生产部署。
  • 可清洗的 。磁盘空间是有限的,就像堆空间一样。我需要删除n几天以前的条目。如果我必须手动执行此操作并不重要。

必备:

  • 易于使用。 如果我能在本周末之前完成这项工作,那就太好了。
    更好的是:一天结束。这将是 非常,非常 巨大的,如果我能一个JAR添加到我的类路径,改变new ConcurrentHashMap<Foo, Bar>();new SomeDiskStoredMap<Foo, Bar>();
    和完成。

  • 良好的 可扩展性和性能。 最坏的情况:每天平均每秒每秒添加3次(平均)新条目。但是,插入操作并不总是那么顺利。(no inserts for an hour)然后可能是(insert 10,000 objects at once)

可能的解决方案

  • 伯克利DB?再说一次,我从未使用过它,我对此一无所知。
  • Hadoop(以及哪个子项目)?没用过。基于这些文档,其跨平台就绪性对我来说是模棱两可的。在可预见的将来,我不需要分布式操作。
  • 一个SQLite的JDBC驱动程序后,所有?
  • ???

Ehcache和Berkeley DB现在都看起来很合理。在任一方向上有什么特别的建议吗?


阅读 204

收藏
2020-12-03

共1个答案

一尘不染

更新(首次发布后约4年…):请注意,在较新版本的ehcache中,缓存项的持久性仅在付费产品中可用。感谢@boday指出这一点。

ehcache很棒。它将为您提供在内存,磁盘或具有溢出到磁盘的内存中实现映射所需的灵活性。如果为java.util.Map使用这个非常简单的包装器,那么使用它就非常简单:

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;

import org.apache.log4j.Logger;

import com.google.common.collect.Sets;

public class EhCacheMapAdapter<K,V> implements Map<K,V> {
    @SuppressWarnings("unused")
    private final static Logger logger = Logger
            .getLogger(EhCacheMapAdapter.class);

    public Cache ehCache;

    public EhCacheMapAdapter(Cache ehCache) {
        super();
        this.ehCache = ehCache;
    } // end constructor

    @Override
    public void clear() {
        ehCache.removeAll();
    } // end method

    @Override
    public boolean containsKey(Object key) {
        return ehCache.isKeyInCache(key);
    } // end method

    @Override
    public boolean containsValue(Object value) {
        return ehCache.isValueInCache(value);
    } // end method

    @Override
    public Set<Entry<K, V>> entrySet() {
        throw new UnsupportedOperationException();
    } // end method

    @SuppressWarnings("unchecked")
    @Override
    public V get(Object key) {
        if( key == null ) return null;
        Element element = ehCache.get(key);
        if( element == null ) return null;
        return (V)element.getObjectValue();
    } // end method

    @Override
    public boolean isEmpty() {
        return ehCache.getSize() == 0;
    } // end method

    @SuppressWarnings("unchecked")
    @Override
    public Set<K> keySet() {
        List<K> l = ehCache.getKeys();
        return Sets.newHashSet(l);
    } // end method

    @SuppressWarnings("unchecked")
    @Override
    public V put(K key, V value) {
        Object o = this.get(key);
        if( o != null ) return (V)o;
        Element e = new Element(key,value);
        ehCache.put(e);
        return null;
    } // end method


    @Override
    public V remove(Object key) {
        V retObj = null;
        if( this.containsKey(key) ) {
            retObj = this.get(key);
        } // end if
        ehCache.remove(key);
        return retObj;
    } // end method

    @Override
    public int size() {
        return ehCache.getSize();
    } // end method

    @Override
    public Collection<V> values() {
        throw new UnsupportedOperationException();
    } // end method

    @Override
    public void putAll(Map<? extends K, ? extends V> m) {
        for( K key : m.keySet() ) {
            this.put(key, m.get(key));
        } // end for
    } // end method
} // end class
2020-12-03