问题
跟进 this question , 似乎是基于文件或磁盘的 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)
.
可能的解决方案
- Ehcache ?我以前从未使用过它。这是一个suggested solution回答我之前的问题。
- Berkeley DB ?再说一次,我从未使用过它,我真的对它一无所知。
- Hadoop (以及哪个子项目)?没用过基于these docs ,它的跨平台准备对我来说是模棱两可的。在可预见的 future ,我不需要分布式操作。
- A SQLite JDBC driver毕竟?
- ???
Ehcache 和 Berkeley DB 现在看起来都很合理。在这两个方向上有什么特别的建议吗?
最佳答案
更新(第一次发布后大约 4 年...):请注意,在较新版本的 ehcache 中,缓存项的持久性仅在付费产品中可用。感谢@boday 指出这一点。
ehcache 很棒。它将为您提供在内存、磁盘或溢出到磁盘的内存中实现映射所需的灵 active 。如果您对 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
关于java - 寻找 java.util.Map 的替代品,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4726370/