MapDB is a high performance pure java database, it provides concurrent collections (Maps, Sets and Queues) backed by disk storage or off-heap memory.
It provides a powerful mechanism to synchronize collections that can be used to build multiple indexes on a primary collection. Follows is an example showing how to index keys and also values of main collection.
1. define a serializable class
2. Define a map of persons by id
3. Define a gender-based index
MapdDB offers multiple ways to define indexes on a given collection, It can also be extended to define specific kind of indexes. Follows is an example of implementing the Bitmap index in MapDB:
Continue here
It provides a powerful mechanism to synchronize collections that can be used to build multiple indexes on a primary collection. Follows is an example showing how to index keys and also values of main collection.
1. define a serializable class
// this class should implement serializable in order to be stored
public class Person implements Serializable {
String firstname;
String lastname;
Integer age;
boolean male;
public Person(String f, String l, Integer a, boolean m) {
this.firstname = f;
this.lastname = l;
this.age = a;
this.male = m;
}
public boolean isMale() {
return male;
}
@Override
public String toString() {
return "Person [firstname=" + firstname + ", lastname=" + lastname + ", age=" + age + ", male=" + male + "]";
}
}
2. Define a map of persons by id
// stores person under id
BTreeMap<Integer, Person> primary = DBMaker.newTempTreeMap();
primary.put(111, new Person("bIs9r", "NWmqoxFf", 92, true));
primary.put(111, new Person("4KXp8", "QrPsabf1", 31, false));
primary.put(111, new Person("eJLIo", "SJwJidWk", 6, true));
primary.put(111, new Person("LGW58", "vteM4khp", 42, false));
primary.put(111, new Person("tIM8R", "Rzq75ONh", 57, false));
primary.put(111, new Person("KqKRE", "BnpUV4dW", 26, true));
3. Define a gender-based index
// stores value hash from primary map
NavigableSet<Fun.Tuple2<Boolean, Integer>> genderIndex = new TreeSet<Fun.Tuple2<Boolean, Integer>>();
//1. gender-based index: bind secondary to primary so it contains secondary key
Bind.secondaryKey(primary, genderIndex, new Fun.Function2<Boolean, Integer, Person>() {
@Override
public Boolean run(Integer key, Person value) {
return Boolean.valueOf(value.isMale());
}
});
4. Use the gender-index to read all male persons
Iterable<Integer> ids = Fun.filter(genderIndex, true);
for(Integer id: ids) {
System.out.println(primary.get(id));
}
MapdDB offers multiple ways to define indexes on a given collection, It can also be extended to define specific kind of indexes. Follows is an example of implementing the Bitmap index in MapDB:
public static <K, V, K2> void secondaryKey(MapWithModificationListener<K, V> map, final Map<K2, Set<K>> secondary,
final Fun.Function2<K2, K, V> fun) {
// fill if empty
if (secondary.isEmpty()) {
for (Map.Entry<K, V> e : map.entrySet()) {
K2 k2 = fun.run(e.getKey(), e.getValue());
Set<K> set = secondary.get(k2);
if (set == null) {
set = new TreeSet<K>();
secondary.put(k2, set);
}
set.add(e.getKey());
}
}
// hook listener
map.modificationListenerAdd(new MapListener<K, V>() {
@Override
public void update(K key, V oldVal, V newVal) {
if (newVal == null) {
// removal
secondary.get(fun.run(key, oldVal)).remove(key);
} else if (oldVal == null) {
// insert
K2 key2 = fun.run(key, newVal);
Set<K> set = secondary.get(key2);
if (set == null) {
set = new TreeSet<K>();
secondary.put(key2, set);
}
set.add(key);
} else {
// update, must remove old key and insert new
K2 oldKey = fun.run(key, oldVal);
K2 newKey = fun.run(key, newVal);
if (oldKey == newKey || oldKey.equals(newKey))
return;
Set<K> set1 = secondary.get(oldKey);
if (set1 != null) {
set1.remove(key);
}
Set<K> set2 = secondary.get(newKey);
if (set2 == null) {
set2 = new TreeSet<K>();
secondary.put(newKey, set2);
}
set2.add(key);
}
}
});
}
This new index can be used as follows:
final Map<Boolean, Set<Integer>> bitmapIndex = new HashMap<Boolean, Set<Integer>>(); secondaryKey(primary, bitmapIndex, fun);
Continue here