code: @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.");
      }
    }
docs: 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