guava/src/com/google/common/collect/FluentIterable.java
public final <K> ImmutableListMultimap<K, E> index(Function<? super E, K> keyFunction) {
    return Multimaps.index(getDelegate(), keyFunction);
  }
public final <K> ImmutableListMultimap<K, E> index(Function<? super E, K> keyFunction) {
    return Multimaps.index(getDelegate(), keyFunction);
  }
Creates an index {@code ImmutableListMultimap} that contains the results of applying a
specified function to each item in this {@code FluentIterable} of values. Each element of this
iterable will be stored as a value in the resulting multimap, yielding a multimap with the same
size as this iterable. The key used to store that value in the multimap will be the result of
calling the function on that value. The resulting multimap is created as an immutable snapshot.
In the returned multimap, keys appear in the order they are first encountered, and the values
corresponding to each key appear in the same order as they are encountered.

<p><b>{@code Stream} equivalent:</b> {@code stream.collect(Collectors.groupingBy(keyFunction))}
behaves similarly, but returns a mutable {@code Map<K, List<E>>} instead, and may not preserve
the order of entries).

@param keyFunction the function used to produce the key for each value
@throws NullPointerException if any element of this iterable is {@code null}, or if {@code
keyFunction} produces {@code null} for any key
@since 14.0