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

edu.isi.nlp.collections.MultimapUtils Maven / Gradle / Ivy

The newest version!
package edu.isi.nlp.collections;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
import java.util.Collection;
import java.util.Map;

/**
 * Utilities for working with {@link Multimap}s.
 *
 * @author Jay DeYoung, Ryan Gabbard
 */
public final class MultimapUtils {

  private MultimapUtils() {
    throw new UnsupportedOperationException();
  }

  /**
   * This will take a multimap which in fact has a single value map for each key and return a copy
   * of it as an {@link com.google.common.collect.ImmutableMap}. If the same key if mapped to
   * multiple values in the input multimap, an {@link java.lang.IllegalArgumentException} is thrown,
   * so this should generally not be used on multimaps built from user input unless this property is
   * guaranteed to hold. This is mostly useful for statically building maps which are more naturally
   * represented as inverted multimaps.
   *
   * 

Preserves iteration order. */ public static Map copyAsMap(Multimap multimap) { final Map> inputAsMap = multimap.asMap(); final ImmutableMap.Builder ret = ImmutableMap.builder(); for (final Map.Entry> mapping : inputAsMap.entrySet()) { ret.put(mapping.getKey(), Iterables.getOnlyElement(mapping.getValue())); } return ret.build(); } /** * Converts a {@link com.google.common.collect.Multimap} to a {@link java.util.Map} by selecting a * single value for each key and discarding the others, with the selection procedure being defined * by {@code reducerFunction}, which may not return {@code null}. Additionally, {@code multimap} * may not have {@code null} keys. */ public static ImmutableMap reduceToMap( Multimap multimap, Function, ? extends V> reducerFunction) { final ImmutableMap.Builder ret = ImmutableMap.builder(); for (final Map.Entry> entry : multimap.asMap().entrySet()) { // nulls banned by contract //noinspection ConstantConditions ret.put(entry.getKey(), reducerFunction.apply(entry.getValue())); } return ret.build(); } /** * Returns an {@link ImmutableSet} of all items in the multimap for the given set of keys, without * preserving mulitiplicity. */ public static ImmutableSet getAllAsSet( final Multimap multimap, final Iterable keys) { final ImmutableSet.Builder ret = ImmutableSet.builder(); for (final K key : keys) { ret.addAll(multimap.get(key)); } return ret.build(); } /** * Performs a (non-strict) composition of two multimaps to an {@link ImmutableSetMultimap}. This * returns a new {@link ImmutableSetMultimap} which will contain an entry {@code (k,v)} if and * only if there is some {@code i} such that {@code (k, i)} is in {@code first} and {@code (i,v)} * is in {@code second}. Neither {@code first} nor {@code second} is permitted to contain null * keys or values. The output of this method is not a view and will not be updated for changes to * the input multimaps. * *

This method will allow {@code first} to contain values not found as keys of {@code second}. * If you wish to disallow this, see {@link #composeToSetMultimapStrictly(Multimap, Multimap)}. */ public static ImmutableSetMultimap composeToSetMultimap( final Multimap first, final Multimap second) { final ImmutableSetMultimap.Builder result = ImmutableSetMultimap.builder(); for (K1 k1 : first.keySet()) { checkNotNull(k1); for (V1 v1 : first.get(k1)) { checkNotNull(v1); result.putAll(k1, second.get(v1)); } } return result.build(); } /** * Performs a (strict) composition of two multimaps to an {@link ImmutableSetMultimap}. This * returns a new {@link ImmutableSetMultimap} which will contain an entry {@code (k,v)} if and * only if there is some {@code i} such that {@code (k, i)} is in {@code first} and {@code (i, v)} * is in {@code second}. Neither {@code first} nor {@code second} is permitted to contain null * keys or values. The output of this method is not a view and will not be updated for changes to * the input multimaps. Strict compositions require that for each entry {@code (k,i)} in {@code * first}, there exists an entry {@code (i,v)} in {@code second}. */ public static ImmutableSetMultimap composeToSetMultimapStrictly( final Multimap first, final Multimap second) { checkArgument(second.keySet().containsAll(first.values())); return composeToSetMultimap(first, second); } /** * Creates a copy of the supplied multimap with its keys transformed by the supplied function. * *

The {@code injection} must never return null and the input multimap must contain no nulls. */ public static ImmutableListMultimap copyWithTransformedKeys( final ListMultimap listMultimap, final Function injection) { final ImmutableListMultimap.Builder ret = ImmutableListMultimap.builder(); for (final Map.Entry entry : listMultimap.entries()) { // nulls banned by contract //noinspection ConstantConditions ret.put(injection.apply(entry.getKey()), entry.getValue()); } return ret.build(); } /** * Creates a copy of the supplied multimap with its keys transformed by the supplied function. * *

The {@code function} must never return null and the input multimap must contain no nulls. */ public static ImmutableSetMultimap copyWithTransformedKeys( final SetMultimap setMultimap, final Function function) { final ImmutableSetMultimap.Builder ret = ImmutableSetMultimap.builder(); for (final Map.Entry entry : setMultimap.entries()) { // nulls banned by contract //noinspection ConstantConditions ret.put(function.apply(entry.getKey()), entry.getValue()); } return ret.build(); } /** * Exactly like {@link Multimaps#index(Iterable, Function)}, except the key function can provide * multiple keys for a given value. The {@code keyFunction} may never return {@code null} or a * collection containing {@code null}. */ public static ImmutableSetMultimap indexToSetMultimapWithMultipleKeys( Iterable values, Function> keyFunction) { final ImmutableSetMultimap.Builder ret = ImmutableSetMultimap.builder(); for (final V value : values) { // nulls banned by contract //noinspection ConstantConditions for (K key : keyFunction.apply(value)) { ret.put(key, value); } } return ret.build(); } /** * Exactly like {@link Multimaps#index(Iterable, Function)}, except the key function can provide * multiple keys for a given value. The {@code keyFunction} may never return {@code null} or a * collection containing {@code null}. */ public static ImmutableListMultimap indexToListMultimapWithMultipleKeys( Iterable values, Function> keyFunction) { final ImmutableListMultimap.Builder ret = ImmutableListMultimap.builder(); for (final V value : values) { // nulls banned by contract //noinspection ConstantConditions for (K key : keyFunction.apply(value)) { ret.put(key, value); } } return ret.build(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy