fr.vergne.multimap.impl.BackedMultiMap Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of multi-map Show documentation
Show all versions of multi-map Show documentation
Provides an interface and implementations of a Java structure able to map a key to several values at once. Initially inspired from the Apache MultiMap, it takes a different perspective where the generics should be fully used to properly constrain the types of the instances provided.
The newest version!
package fr.vergne.multimap.impl;
import java.util.AbstractMap;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Supplier;
import fr.vergne.multimap.MultiMap;
/**
* A {@link BackedMultiMap} is a {@link MultiMap} which implements its fetures
* above a {@link Map} instance. In other words, any modification made to the
* {@link Map} is reflected on the {@link BackedMultiMap} and vice-versa.
*
* @author Matthieu Vergne
*
* @param
* @param
*/
public class BackedMultiMap implements MultiMap {
private final Map> map;
private final Supplier> collectionSupplier;
public BackedMultiMap(Map> map, Supplier> collectionSupplier) {
this.map = map;
this.collectionSupplier = collectionSupplier;
}
@Override
public boolean add(Key key, Value value) {
Collection set = getContainerFor(key);
return set.add(value);
}
@Override
public boolean addAll(Key key, Collection values) {
Collection set = getContainerFor(key);
return set.addAll(values);
}
@Override
public boolean remove(Key key, Value value) {
Collection set = getContainerFor(key);
return set.remove(value);
}
@Override
public boolean removeAll(Key key, Collection values) {
Collection set = getContainerFor(key);
return set.removeAll(values);
}
private Collection getContainerFor(Key key) {
if (!containsKey(key)) {
map.put(key, collectionSupplier.get());
} else {
// use the already present collection
}
return map.get(key);
}
@Override
public boolean containsCouple(Key key, Value value) {
return containsKey(key) && map.get(key).contains(value);
}
@Override
public Iterator> iterator() {
return new Iterator>() {
private Iterator keysIterator = keySet().iterator();
private Iterator valuesIterator;
private Key key;
private Value value;
@Override
public boolean hasNext() {
return keysIterator.hasNext() || valuesIterator != null && valuesIterator.hasNext();
}
@Override
public Entry next() {
while (valuesIterator == null || !valuesIterator.hasNext()) {
key = keysIterator.next();
valuesIterator = BackedMultiMap.this.map.get(key).iterator();
}
value = valuesIterator.next();
return new AbstractMap.SimpleImmutableEntry(key, value);
}
@Override
public void remove() {
BackedMultiMap.this.remove(key, value);
}
};
}
@Override
public Collection replaceAll(Key key, Collection collection) {
Collection actualCollection = collectionSupplier.get();
actualCollection.addAll(collection);
return map.put(key, actualCollection);
}
@Override
public Collection getAll(Object key) {
return map.get(key);
}
@Override
public Set keySet() {
return map.keySet();
}
@Override
public Collection> collections() {
return map.values();
}
@Override
public Set>> entrySet() {
return map.entrySet();
}
@Override
public Collection remove(Object key) {
return map.remove(key);
}
@Override
public void clear() {
map.clear();
}
@Override
public boolean containsKey(Object key) {
return map.containsKey(key);
}
@Override
public boolean containsKeyMappedTo(Collection collection) {
Collection typedCollection = collectionSupplier.get();
typedCollection.addAll(collection);
return map.containsValue(typedCollection);
}
@Override
public int size() {
return map.size();
}
/**
* @return the {@link Map} backed by this {@link BackedMultiMap}
*/
@Override
public Map> toMap() {
return map;
}
public static BackedMultiMap onLists() {
return new BackedMultiMap<>(new HashMap<>(), () -> new LinkedList<>());
}
public static BackedMultiMap onSets() {
return new BackedMultiMap<>(new HashMap<>(), () -> new HashSet<>());
}
}