fr.vergne.collection.impl.AbstractMultiMap Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of collection-core Show documentation
Show all versions of collection-core Show documentation
Implementation of the collection facilities.
package fr.vergne.collection.impl;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import fr.vergne.collection.MultiMap;
/**
* An {@link AbstractMultiMap} is a {@link MultiMap} which implements most of
* the features. It is basically a {@link HashMap}, so a given key appears only
* once. However, the type of collection used for values is not provided, which
* leads to a method to implement in the classes which extend this
* {@link AbstractMultiMap}.
*
* @author Matthieu Vergne
*
* @param
* @param
*/
@SuppressWarnings("serial")
public abstract class AbstractMultiMap extends
HashMap> implements MultiMap {
public AbstractMultiMap(MultiMap map) {
for (Entry> entry : map.entrySet()) {
populate(entry.getKey(), entry.getValue());
}
}
public AbstractMultiMap() {
}
@Override
public final boolean populate(Key key, Value... values) {
return populate(key, Arrays.asList(values));
}
@Override
public final boolean populate(Key key, Collection values) {
Collection set = getContainerFor(key);
return set.addAll(values);
}
@Override
public final boolean depopulate(Key key, Value... values) {
return depopulate(key, Arrays.asList(values));
}
@Override
public final boolean depopulate(Key key, Collection values) {
Collection set = getContainerFor(key);
boolean changed = set.removeAll(values);
if (set.isEmpty()) {
remove(key);
} else {
// still have values, keep the key
}
return changed;
}
private Collection getContainerFor(Key key) {
if (!containsKey(key)) {
put(key, generateInnerCollection(key));
} else {
// use the already present collection
}
return get(key);
}
protected abstract Collection generateInnerCollection(Key key);
@Override
public boolean containsCouple(Key key, Value value) {
return containsKey(key) && 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 = AbstractMultiMap.this.get(key).iterator();
}
value = valuesIterator.next();
return new SimpleImmutableEntry(key, value);
}
@SuppressWarnings("unchecked")
@Override
public void remove() {
AbstractMultiMap.this.depopulate(key, value);
}
};
}
}