All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fr.vergne.multimap.impl.BackedMultiMap Maven / Gradle / Ivy

Go to download

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<>());
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy