org.eclipse.collections.api.multimap.Multimap Maven / Gradle / Ivy
/*
* Copyright (c) 2019 Goldman Sachs.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v. 1.0 which accompany this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*/
package org.eclipse.collections.api.multimap;
import java.util.Collection;
import org.eclipse.collections.api.RichIterable;
import org.eclipse.collections.api.bag.Bag;
import org.eclipse.collections.api.block.function.Function;
import org.eclipse.collections.api.block.function.Function0;
import org.eclipse.collections.api.block.function.Function2;
import org.eclipse.collections.api.block.predicate.Predicate2;
import org.eclipse.collections.api.block.procedure.Procedure;
import org.eclipse.collections.api.block.procedure.Procedure2;
import org.eclipse.collections.api.map.MutableMap;
import org.eclipse.collections.api.set.SetIterable;
import org.eclipse.collections.api.tuple.Pair;
/**
* This collection is a type of {@code Map} that can associate multiple values for keys.
*
* Unlike {@code Map} however, this interface is read-only so the results of access methods such as {@link
* #get(Object)} return a view onto the values associated with that key. The {@link MutableMultimap} sub-interface
* provides methods to mutate the collection.
*
* The advantages to using this container over a {@code Map>} is that all of the handling of the
* value collection can be done automatically. It also allows implementations to further specialize in how duplicate
* values will be handled. Value collections with list semantics would allow duplicate values for a key, while those
* implementing set semantics would not. The value collections can never be empty.
*
* Internal iteration methods for keys and values (singly - {@link #forEachKey(Procedure)}, {@link #forEachValue(Procedure)},
* and together - {@link #forEachKeyValue(Procedure2)}), {@link #forEachKeyMultiValues(Procedure2)}) are provided to allow flexible
* browsing of the collection's contents. Similarly, views also are provided for keys ({@link #keysView()}), values
* ({@link #valuesView()}) and the combination thereof ({@link #keyValuePairsView()}, {@link #keyMultiValuePairsView()}).
*
* @param the type of keys used
* @param the type of mapped values
* @since 1.0
*/
@SuppressWarnings("JavaDoc")
public interface Multimap
{
/**
* Creates a new instance of the same implementation type, using the default capacity and growth parameters.
*/
Multimap newEmpty();
/**
* Returns {@code true} if there are no entries.
*/
boolean isEmpty();
/**
* Returns {@code true} if there is at least one entry.
*/
boolean notEmpty();
/**
* Calls the procedure with each value.
* Given a Multimap with the contents:
*
* {@code {"key1" : ["val1", "val2", "val2"], "key2" : ["val3"]}}
*
* The given procedure would be invoked with the parameters:
*
* {@code ["val1", "val2", "val2", "val3"]}
*
*/
void forEachValue(Procedure super V> procedure);
/**
* Calls the {@code procedure} with each key.
* Given a Multimap with the contents:
*
* {@code {"key1" : ["val1", "val2", "val2"], "key2" : ["val3"]}}
*
*
* The given procedure would be invoked with the parameters:
*
*
* {@code ["key1", "key2"]}
*
*/
void forEachKey(Procedure super K> procedure);
/**
* Calls the {@code procedure} with each key-value pair.
* Given a Multimap with the contents:
*
* {@code {"key1" : ["val1", "val2", "val2"], "key2" : ["val3"]}}
*
*
* The given procedure would be invoked with the parameters:
*
*
* {@code [["key1", "val1"], ["key1", "val2"], ["key1", "val2"], ["key2", "val3"]]}
*
*/
void forEachKeyValue(Procedure2 super K, ? super V> procedure);
/**
* Calls the {@code procedure} with each key-Iterable[value].
* Given a Multimap with the contents:
*
* {@code {"key1" : ["val1", "val2", "val2"], "key2" : ["val3"]}}
*
*
* The given procedure would be invoked with the parameters:
*
*
* {@code [["key1", {@link RichIterable["val1", "val2", "val2"]}], ["key2", {@link RichIterable["val3"]}]]}
*
*
* @since 6.0
*/
void forEachKeyMultiValues(Procedure2 super K, ? super Iterable> procedure);
/**
* Returns the number of key-value entry pairs.
* This method is implemented with O(1) (constant-time) performance.
*/
int size();
/**
* Returns the number of distinct keys.
*/
int sizeDistinct();
/**
* Returns {@code true} if any values are mapped to the specified key.
*
* @param key the key to search for
*/
boolean containsKey(Object key);
/**
* Returns {@code true} if any key is mapped to the specified value.
*
* @param value the value to search for
*/
boolean containsValue(Object value);
/**
* Returns {@code true} if the specified key-value pair is mapped.
*
* @param key the key to search for
* @param value the value to search for
*/
boolean containsKeyAndValue(Object key, Object value);
/**
* Returns a view of all values associated with the given key.
* If the given key does not exist, an empty {@link RichIterable} is returned.
*
* @param key the key to search for
*/
RichIterable get(K key);
/**
* Returns a lazy view of the unique keys.
*/
RichIterable keysView();
/**
* Returns a unmodifiable {@link SetIterable} of keys with O(1) complexity.
*/
SetIterable keySet();
/**
* Returns a {@link Bag} of keys with the count corresponding to the number of mapped values.
*/
Bag keyBag();
/**
* Returns an unmodifiable view of all of the values mapped to each key.
*/
RichIterable> multiValuesView();
/**
* Returns a lazy flattened view of all the values.
*/
RichIterable valuesView();
/**
* Returns a lazy view of the pair of a key and and a lazy view of the values mapped to that key.
*/
RichIterable>> keyMultiValuePairsView();
/**
* Returns a lazy view of all of the key/value pairs.
*/
RichIterable> keyValuePairsView();
/**
* Returns a new {@link MutableMap} of keys from this Multimap to the mapped values as a {@link RichIterable}.
*/
MutableMap> toMap();
/**
* Returns a new {@link MutableMap} of keys from this Multimap to the mapped values as a {@link RichIterable}.
*
* @param collectionFactory used to create the collections that hold the values and affects the return type
*/
> MutableMap toMap(Function0 collectionFactory);
/**
* Compares the specified object with this Multimap for equality.
* Two Multimaps are equal when their map views (as returned by {@link #toMap}) are also equal.
* In general, two Multimaps with identical key-value mappings may or may not be equal, depending on the type of
* the collections holding the values. If the backing collections are Sets, then two instances with the same
* key-value mappings are equal, but if the backing collections are Lists, equality depends on the ordering of the
* values for each key.
* Any two empty Multimaps are equal, because they both have empty {@link #toMap} views.
*/
@Override
boolean equals(Object obj);
/**
* Returns the hash code for this Multimap.
* The hash code of a Multimap is defined as the hash code of the map view, as returned by {@link #toMap}.
*/
@Override
int hashCode();
/**
* Returns a mutable copy of this Multimap.
*/
MutableMultimap toMutable();
/**
* Returns an immutable copy of this Multimap if it is not already immutable. If the Multimap is immutable,
* it will return itself.
* The returned Multimap will be {@code Serializable} if this Multimap is {@code Serializable}.
*/
ImmutableMultimap toImmutable();
/**
* Given a Multimap from Domain {@code ->} Range return a multimap from Range {@code ->} Domain.
*
* @since 6.0
*/
Multimap flip();
/**
* Returns all elements of the source multimap that satisfies the predicate. This method is also
* commonly called filter.
*
* e.g.
* return multimap.selectKeysValues(new Predicate2<Integer, Person>()
* {
* public boolean accept(Integer age, Person person)
* {
* return (age >= 18)
* && (person.getAddress().getCity().equals("Metuchen"));
* }
* });
*
*
* @param predicate a {@link Predicate2} to use as the select criteria
* @return {@code Multimap}, which contains elements as a result of the select criteria
* @since 6.0
*/
Multimap selectKeysValues(Predicate2 super K, ? super V> predicate);
/**
* Same as the select method but uses the specified target multimap for the results.
*
* e.g.
* return multimap.selectKeysValues(new Predicate2<Integer, Person>()
* {
* public boolean accept(Integer age, Person person)
* {
* return (age >= 18)
* && (person.getAddress().getCity().equals("Metuchen"));
* }
* }, FastListMultimap.newMultimap());
*
*
* @param predicate a {@link Predicate2} to use as the select criteria
* @param target the Multimap to append to for all elements in this {@code Multimap} that satisfy the {@code predicate}
* @return {@code target}, which contains appended elements as a result of the select criteria
* @since 6.0
*/
> R selectKeysValues(Predicate2 super K, ? super V> predicate, R target);
/**
* Returns all elements of the source multimap that don't satisfy the predicate.
*
* e.g.
* return multimap.rejectKeysValues(new Predicate2<Integer, Person>()
* {
* public boolean accept(Integer age, Person person)
* {
* return (age >= 18)
* && (person.getAddress().getCity().equals("Metuchen"));
* }
* });
*
*
* @param predicate a {@link Predicate2} to use as the reject criteria
* @return {@code Multimap}, which contains elements that don't satisfy the {@code predicate}
* @since 6.0
*/
Multimap rejectKeysValues(Predicate2 super K, ? super V> predicate);
/**
* Same as the reject method but uses the specified target multimap for the results.
*
* e.g.
* return multimap.rejectKeysValues(new Predicate2<Integer, Person>()
* {
* public boolean accept(Integer age, Person person)
* {
* return (age >= 18)
* && (person.getAddress().getCity().equals("Metuchen"));
* }
* }, FastListMultimap.newMultimap());
*
*
* @param predicate a {@link Predicate2} to use as the reject criteria
* @param target the Multimap to append to for all elements in this {@code Multimap} that don't satisfy the {@code predicate}
* @return {@code target}, which contains appended elements that don't satisfy the {@code predicate}
* @since 6.0
*/
> R rejectKeysValues(Predicate2 super K, ? super V> predicate, R target);
/**
* Returns all elements of the source multimap that satisfies the predicate. This method is also
* commonly called filter.
*
* e.g.
* return multimap.selectKeysMultiValues(new Predicate2<Integer, Iterable<Person>>()
* {
* public boolean accept(Integer age, Iterable<Person> values)
* {
* return (age >= 18)
* && ((RichIterable<Person>)values.size() >= 2);
* }
* });
*
*
* @param predicate a {@link Predicate2} to use as the select criteria
* @return {@code Multimap}, which contains elements as a result of the select criteria
* @since 6.0
*/
Multimap selectKeysMultiValues(Predicate2 super K, ? super Iterable> predicate);
/**
* Same as the select method but uses the specified target multimap for the results.
*
* e.g.
* return multimap.selectKeysMultiValues(new Predicate2<Integer, Iterable<Person>>()
* {
* public boolean accept(Integer age, Iterable<Person> values)
* {
* return (age >= 18)
* && ((RichIterable<Person>)values.size() >= 2);
* }
* }, FastListMultimap.newMultimap());
*
*
* @param predicate a {@link Predicate2} to use as the select criteria
* @param target the Multimap to append to for all elements in this {@code Multimap} that satisfy the {@code predicate}
* @return {@code target}, which contains appended elements as a result of the select criteria
* @since 6.0
*/
> R selectKeysMultiValues(Predicate2 super K, ? super Iterable> predicate, R target);
/**
* Returns all elements of the source multimap that don't satisfy the predicate.
*
* e.g.
* return multimap.rejectKeysMultiValues(new Predicate2<Integer, Iterable<Person>>()
* {
* public boolean accept(Integer age, Iterable<Person> values)
* {
* return (age >= 18)
* && ((RichIterable<Person>)values.size() >= 2);
* }
* });
*
*
* @param predicate a {@link Predicate2} to use as the reject criteria
* @return {@code Multimap}, which contains elements that don't satisfy the {@code predicate}
* @since 6.0
*/
Multimap rejectKeysMultiValues(Predicate2 super K, ? super Iterable> predicate);
/**
* Same as the reject method but uses the specified target multimap for the results.
*
* e.g.
* return multimap.rejectKeysMultiValues(new Predicate2<Integer, Iterable<Person>>()
* {
* public boolean accept(Integer age, Iterable<Person> values)
* {
* return (age >= 18)
* && ((RichIterable<Person>)values.size() >= 2);
* }
* }, FastListMultimap.newMultimap());
*
*
* @param predicate a {@link Predicate2} to use as the reject criteria
* @param target the Multimap to append to for all elements in this {@code Multimap} that don't satisfy the {@code predicate}
* @return {@code target}, which contains appended elements that don't satisfy the {@code predicate}
* @since 6.0
*/
> R rejectKeysMultiValues(Predicate2 super K, ? super Iterable> predicate, R target);
/**
* Returns a new multimap with the results of applying the specified function on each key and value of the source
* multimap. This method is also commonly called transform or map.
*
* e.g.
* return multimap.collectKeysValues(new Function2<Integer, Person, Pair<String, String>>()
* {
* public Pair<String, String> valueOf(Integer age, Person person)
* {
* return Tuples.pair(age.toString(), person.getLastName());
* }
* });
*
*
* @param function a {@link Function2} to use for transformation
* @return {@code Multimap}, which contains elements as a result of the transformation
* @since 6.0
*/
Multimap collectKeysValues(Function2 super K, ? super V, Pair> function);
/**
* Same as the collect method but uses the specified target multimap for the results.
*
* e.g.
* return multimap.collectKeysValues(new Function2<Integer, Person, Pair<String, String>>()
* {
* public Pair<String, String> valueOf(Integer age, Person person)
* {
* return Tuples.pair(age.toString(), person.getLastName());
* }
* }, HashBagMultimap.<String, String>newMultimap());
*
*
* @param function a {@link Function2} to use for transformation
* @param target the Multimap to append for all elements in this {@code Multimap} that are evaluated in {@code function}
* @return {@code target}, which contains appended elements as a result of the transformation
* @since 6.0
*/
> R collectKeysValues(Function2 super K, ? super V, Pair> function, R target);
/**
* Returns a new multimap with the results of applying the specified keyFunction and valueFunction on each key and corresponding values of the source multimap.
* This method is also commonly called transform or map.
*
* e.g.
* return multimap.collectKeyMultiValues(each -> each + 1, Person::getLastName);
*
*
* @param keyFunction {@link Function} to use transformation to get the key
* @param valueFunction {@link Function} to use transformation to get the values
* @return a new {@code Multimap}, which contains elements as a result of the transformation
* @since 10.0
*/
Multimap collectKeyMultiValues(Function super K, ? extends K2> keyFunction, Function super V, ? extends V2> valueFunction);
/**
* Same as the collectKeyMultiValues method but uses the specified target multimap for the results.
*
* e.g.
* return multimap.collectKeyMultiValues(each -> each + 1, Person::getLastName, HashBagMultimap.<Integer, String>newMultimap());
*
*
* @param keyFunction {@link Function} to use transformation to get the key
* @param valueFunction {@link Function} to use transformation to get the values
* @param target the Multimap to append for all elements in this {@code Multimap} that are evaluated in {@code keyFunction} and {@code valueFunction}
* @return {@code target}, which contains appended elements as a result of the transformation
* @since 10.0
*/
> R collectKeyMultiValues(Function super K, ? extends K2> keyFunction, Function super V, ? extends V2> valueFunction, R target);
/**
* Returns a new multimap with the results of applying the specified function on each value of the source
* multimap. This method is also commonly called transform or map.
*
* e.g.
* return multimap.collectValues(new Function<Person, String>()
* {
* public String valueOf(Person person)
* {
* return person.getLastName();
* }
* });
*
*
* @param function a {@link Function} to use for transformation
* @return {@code Multimap}, which contains elements as a result of the transformation
* @since 6.0
*/
Multimap collectValues(Function super V, ? extends V2> function);
/**
* Same as the collect method but uses the specified target multimap for the results.
*
* e.g.
* return multimap.collectValues(new Function<Person, String>()
* {
* public String valueOf(Person person)
* {
* return person.getLastName();
* }
* }, FastListMultimap.<Integer, String>newMultimap());
*
*
* @param function a {@link Function} to use for transformation
* @param target the Multimap to append for all elements in this {@code Multimap} that are evaluated in {@code function}
* @return {@code target}, which contains appended elements as a result of the transformation
* @since 6.0
*/
> R collectValues(Function super V, ? extends V2> function, R target);
}