package org.molgenis.util;
import org.mapdb.DB;
import org.mapdb.DBMaker;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class HugeMap<K, V> implements Map<K, V>, Closeable
{
protected static final int THRESHOLD = 10000;
private DB mapDB;
private Map<K, V> map;
private final Map<K, V> hashMap = new HashMap<>();
@Override
public int size()
{
if (map == null) return hashMap.size();
return map.size();
}
@Override
public boolean isEmpty()
{
if (map == null) return hashMap.isEmpty();
return map.isEmpty();
}
@Override
public boolean containsKey(Object key)
{
if (map == null) return hashMap.containsKey(key);
return map.containsKey(key);
}
@Override
public boolean containsValue(Object value)
{
if (map == null) return hashMap.containsValue(value);
return map.containsValue(value);
}
@Override
public V get(Object key)
{
if (map == null) return hashMap.get(key);
return map.get(key);
}
@Override
public V put(K key, V value)
{
if (hashMap.size() == THRESHOLD)
{
File dbFile;
try
{
dbFile = File.createTempFile("mapdb", "temp");
}
catch (IOException e)
{
throw new UncheckedIOException(e);
}
mapDB = DBMaker.newFileDB(dbFile).deleteFilesAfterClose().transactionDisable().make();
map = mapDB.createHashMap("map").make();
map.putAll(hashMap);
hashMap.clear();
}
if (map == null)
{
return hashMap.put(key, value);
}
return map.put(key, value);
}
@Override
public V remove(Object key)
{
if (map == null) return hashMap.remove(key);
return map.remove(key);
}
@Override
public void putAll(Map<? extends K, ? extends V> m)
{
m.forEach((k, v) -> put(k, v));
}
@Override
public void clear()
{
if (map == null)
{
hashMap.clear();
}
else
{
map.clear();
}
}
@Override
public Set<K> keySet()
{
if (map == null) return hashMap.keySet();
return map.keySet();
}
@Override
public Collection<V> values()
{
if (map == null) return hashMap.values();
return map.values();
}
@Override
public Set<java.util.Map.Entry<K, V>> entrySet()
{
if (map == null) return hashMap.entrySet();
return map.entrySet();
}
@Override
public void close() throws IOException
{
if (mapDB != null)
{
mapDB.close();
}
}
}