android/guava/src/com/google/common/collect/Maps.java
@CanIgnoreReturnValue
  public static <K, V> ImmutableMap<K, V> uniqueIndex(
      Iterator<V> values, Function<? super V, K> keyFunction) {
    checkNotNull(keyFunction);
    ImmutableMap.Builder<K, V> builder = ImmutableMap.builder();
    while (values.hasNext()) {
      V value = values.next();
      builder.put(keyFunction.apply(value), value);
    }
    try {
      return builder.build();
    } catch (IllegalArgumentException duplicateKeys) {
      throw new IllegalArgumentException(
          duplicateKeys.getMessage()
              + ". To index multiple values under a key, use Multimaps.index.");
    }
  }
@CanIgnoreReturnValue
  public static <K, V> ImmutableMap<K, V> uniqueIndex(
      Iterator<V> values, Function<? super V, K> keyFunction) {
    checkNotNull(keyFunction);
    ImmutableMap.Builder<K, V> builder = ImmutableMap.builder();
    while (values.hasNext()) {
      V value = values.next();
      builder.put(keyFunction.apply(value), value);
    }
    try {
      return builder.build();
    } catch (IllegalArgumentException duplicateKeys) {
      throw new IllegalArgumentException(
          duplicateKeys.getMessage()
              + ". To index multiple values under a key, use Multimaps.index.");
    }
  }
@ CanIgnoreReturnValue public static < K , V > ImmutableMap < K , V > uniqueIndex ( Iterator < V > values , Function < ? super V , K > keyFunction ) { checkNotNull ( keyFunction ) ; ImmutableMap . Builder < K , V > builder = ImmutableMap . builder ( ) ; while ( values . hasNext ( ) ) { V value = values . next ( ) ; builder . put ( keyFunction . apply ( value ) , value ) ; } try { return builder . build ( ) ; } catch ( IllegalArgumentException duplicateKeys ) { throw new IllegalArgumentException ( duplicateKeys . getMessage ( ) + ". To index multiple values under a key, use Multimaps.index." ) ; } }
Returns a map with the given {@code values}, indexed by keys derived from those values. In
other words, each input value produces an entry in the map whose key is the result of applying
{@code keyFunction} to that value. These entries appear in the same order as the input values.
Example usage:

<pre>{@code
Color red = new Color("red", 255, 0, 0);
...
Iterator<Color> allColors = ImmutableSet.of(red, green, blue).iterator();

Map<String, Color> colorForName =
uniqueIndex(allColors, toStringFunction());
assertThat(colorForName).containsEntry("red", red);
}</pre>

<p>If your index may associate multiple values with each key, use {@link
Multimaps#index(Iterator, Function) Multimaps.index}.

@param values the values to use when constructing the {@code Map}
@param keyFunction the function used to produce the key for each value
@return a map mapping the result of evaluating the function {@code keyFunction} on each value
in the input collection to that value
@throws IllegalArgumentException if {@code keyFunction} produces the same key for more than one
value in the input collection
@throws NullPointerException if any element of {@code values} is {@code null}, or if {@code
keyFunction} produces {@code null} for any value
@since 10.0
Returns a map with the given { @code values } indexed by keys derived from those values . In other words each input value produces an entry in the map whose key is the result of applying { @code keyFunction } to that value . These entries appear in the same order as the input values . Example usage :