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.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* Set that can contain a huge amount of data by storing it on disk.
*
* @param <E>
*/
public class HugeSet<E> implements Set<E>, Closeable
{
protected static final int THRESHOLD = 10000;
private DB mapDB;
private Set<E> set;
private final HashSet<E> hashSet = new HashSet<>();
@Override
public int size()
{
if (set == null) return hashSet.size();
return set.size();
}
@Override
public boolean isEmpty()
{
if (set == null) return hashSet.isEmpty();
return set.isEmpty();
}
@Override
public boolean contains(Object o)
{
if (set == null) return hashSet.contains(o);
return set.contains(o);
}
@Override
public Iterator<E> iterator()
{
if (set == null) return hashSet.iterator();
return set.iterator();
}
@Override
public Object[] toArray()
{
if (set == null) return hashSet.toArray();
return set.toArray();
}
@Override
public <T> T[] toArray(T[] a)
{
if (set == null) return hashSet.toArray(a);
return set.toArray(a);
}
@Override
public boolean add(E obj)
{
if (hashSet.size() == THRESHOLD)
{
File dbFile;
try
{
dbFile = File.createTempFile("mapdb", "temp");
}
catch (IOException e)
{
throw new UncheckedIOException(e);
}
mapDB = DBMaker.newFileDB(dbFile).deleteFilesAfterClose().transactionDisable().make();
set = mapDB.createHashSet("set").make();
set.addAll(hashSet);
hashSet.clear();
}
if (set == null)
{
return hashSet.add(obj);
}
return set.add(obj);
}
@Override
public boolean remove(Object o)
{
if (set == null) return hashSet.remove(o);
return set.remove(o);
}
@Override
public boolean containsAll(Collection<?> c)
{
if (set == null) return hashSet.containsAll(c);
return set.containsAll(c);
}
@Override
public boolean addAll(Collection<? extends E> c)
{
c.forEach(this::add);
return true;
}
@Override
public boolean retainAll(Collection<?> c)
{
if (set == null) return hashSet.retainAll(c);
return set.retainAll(c);
}
@Override
public boolean removeAll(Collection<?> c)
{
if (set == null) return hashSet.removeAll(c);
return set.removeAll(c);
}
@Override
public void clear()
{
if (set == null)
{
hashSet.clear();
}
else
{
set.clear();
}
}
@Override
public void close() throws IOException
{
if (mapDB != null)
{
mapDB.close();
}
}
}