001/*
002 * Copyright (C) 2008 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package com.google.common.collect;
018
019import static com.google.common.base.Preconditions.checkNotNull;
020import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
021import static com.google.common.collect.CollectPreconditions.checkNonnegative;
022import static com.google.common.collect.Iterators.emptyIterator;
023import static com.google.common.collect.Maps.immutableEntry;
024import static java.lang.Math.max;
025import static java.util.Arrays.asList;
026import static java.util.Objects.requireNonNull;
027
028import com.google.common.annotations.GwtCompatible;
029import com.google.common.annotations.GwtIncompatible;
030import com.google.common.annotations.J2ktIncompatible;
031import com.google.errorprone.annotations.CanIgnoreReturnValue;
032import com.google.errorprone.annotations.DoNotCall;
033import com.google.errorprone.annotations.DoNotMock;
034import com.google.j2objc.annotations.Weak;
035import com.google.j2objc.annotations.WeakOuter;
036import java.io.InvalidObjectException;
037import java.io.ObjectInputStream;
038import java.io.Serializable;
039import java.util.Collection;
040import java.util.Comparator;
041import java.util.Iterator;
042import java.util.Map;
043import java.util.Map.Entry;
044import java.util.Set;
045import java.util.Spliterator;
046import java.util.function.BiConsumer;
047import org.jspecify.annotations.Nullable;
048
049/**
050 * A {@link Multimap} whose contents will never change, with many other important properties
051 * detailed at {@link ImmutableCollection}.
052 *
053 * <p><b>Warning:</b> avoid <i>direct</i> usage of {@link ImmutableMultimap} as a type (as with
054 * {@link Multimap} itself). Prefer subtypes such as {@link ImmutableSetMultimap} or {@link
055 * ImmutableListMultimap}, which have well-defined {@link #equals} semantics, thus avoiding a common
056 * source of bugs and confusion.
057 *
058 * <p><b>Note:</b> every {@link ImmutableMultimap} offers an {@link #inverse} view, so there is no
059 * need for a distinct {@code ImmutableBiMultimap} type.
060 *
061 * <p><a id="iteration"></a>
062 *
063 * <p><b>Key-grouped iteration.</b> All view collections follow the same iteration order. In all
064 * current implementations, the iteration order always keeps multiple entries with the same key
065 * together. Any creation method that would customarily respect insertion order (such as {@link
066 * #copyOf(Multimap)}) instead preserves key-grouped order by inserting entries for an existing key
067 * immediately after the last entry having that key.
068 *
069 * <p>See the Guava User Guide article on <a href=
070 * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">immutable collections</a>.
071 *
072 * @author Jared Levy
073 * @since 2.0
074 */
075@GwtCompatible
076public abstract class ImmutableMultimap<K, V> extends BaseImmutableMultimap<K, V>
077    implements Serializable {
078
079  /**
080   * Returns an empty multimap.
081   *
082   * <p><b>Performance note:</b> the instance returned is a singleton.
083   */
084  public static <K, V> ImmutableMultimap<K, V> of() {
085    return ImmutableListMultimap.of();
086  }
087
088  /** Returns an immutable multimap containing a single entry. */
089  public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1) {
090    return ImmutableListMultimap.of(k1, v1);
091  }
092
093  /** Returns an immutable multimap containing the given entries, in order. */
094  public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1, K k2, V v2) {
095    return ImmutableListMultimap.of(k1, v1, k2, v2);
096  }
097
098  /**
099   * Returns an immutable multimap containing the given entries, in the "key-grouped" insertion
100   * order described in the <a href="#iteration">class documentation</a>.
101   */
102  public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
103    return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3);
104  }
105
106  /**
107   * Returns an immutable multimap containing the given entries, in the "key-grouped" insertion
108   * order described in the <a href="#iteration">class documentation</a>.
109   */
110  public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
111    return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3, k4, v4);
112  }
113
114  /**
115   * Returns an immutable multimap containing the given entries, in the "key-grouped" insertion
116   * order described in the <a href="#iteration">class documentation</a>.
117   */
118  public static <K, V> ImmutableMultimap<K, V> of(
119      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
120    return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5);
121  }
122
123  // looking for of() with > 5 entries? Use the builder instead.
124
125  /**
126   * Returns a new builder. The generated builder is equivalent to the builder created by the {@link
127   * Builder} constructor.
128   */
129  public static <K, V> Builder<K, V> builder() {
130    return new Builder<>();
131  }
132
133  /**
134   * Returns a new builder with a hint for how many distinct keys are expected to be added. The
135   * generated builder is equivalent to that returned by {@link #builder}, but may perform better if
136   * {@code expectedKeys} is a good estimate.
137   *
138   * @throws IllegalArgumentException if {@code expectedKeys} is negative
139   * @since 33.3.0
140   */
141  public static <K, V> Builder<K, V> builderWithExpectedKeys(int expectedKeys) {
142    checkNonnegative(expectedKeys, "expectedKeys");
143    return new Builder<>(expectedKeys);
144  }
145
146  /**
147   * A builder for creating immutable multimap instances, especially {@code public static final}
148   * multimaps ("constant multimaps"). Example:
149   *
150   * {@snippet :
151   * static final Multimap<String, Integer> STRING_TO_INTEGER_MULTIMAP =
152   *     new ImmutableMultimap.Builder<String, Integer>()
153   *         .put("one", 1)
154   *         .putAll("several", 1, 2, 3)
155   *         .putAll("many", 1, 2, 3, 4, 5)
156   *         .build();
157   * }
158   *
159   * <p>Builder instances can be reused; it is safe to call {@link #build} multiple times to build
160   * multiple multimaps in series. Each multimap contains the key-value mappings in the previously
161   * created multimaps.
162   *
163   * @since 2.0
164   */
165  @DoNotMock
166  public static class Builder<K, V> {
167    @Nullable Map<K, ImmutableCollection.Builder<V>> builderMap;
168    @Nullable Comparator<? super K> keyComparator;
169    @Nullable Comparator<? super V> valueComparator;
170    int expectedValuesPerKey = ImmutableCollection.Builder.DEFAULT_INITIAL_CAPACITY;
171
172    /**
173     * Creates a new builder. The returned builder is equivalent to the builder generated by {@link
174     * ImmutableMultimap#builder}.
175     */
176    public Builder() {}
177
178    /** Creates a new builder with a hint for the number of distinct keys. */
179    Builder(int expectedKeys) {
180      if (expectedKeys > 0) {
181        builderMap = Platform.preservesInsertionOrderOnPutsMapWithExpectedSize(expectedKeys);
182      }
183      // otherwise, leave it null to be constructed lazily
184    }
185
186    Map<K, ImmutableCollection.Builder<V>> ensureBuilderMapNonNull() {
187      Map<K, ImmutableCollection.Builder<V>> result = builderMap;
188      if (result == null) {
189        result = Platform.preservesInsertionOrderOnPutsMap();
190        builderMap = result;
191      }
192      return result;
193    }
194
195    ImmutableCollection.Builder<V> newValueCollectionBuilderWithExpectedSize(int expectedSize) {
196      return ImmutableList.builderWithExpectedSize(expectedSize);
197    }
198
199    /**
200     * Provides a hint for how many values will be associated with each key newly added to the
201     * builder after this call. This does not change semantics, but may improve performance if
202     * {@code expectedValuesPerKey} is a good estimate.
203     *
204     * <p>This may be called more than once; each newly added key will use the most recent call to
205     * {@link #expectedValuesPerKey} as its hint.
206     *
207     * @throws IllegalArgumentException if {@code expectedValuesPerKey} is negative
208     * @since 33.3.0
209     */
210    @CanIgnoreReturnValue
211    public Builder<K, V> expectedValuesPerKey(int expectedValuesPerKey) {
212      checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
213
214      // Always presize to at least 1, since we only bother creating a value collection if there's
215      // at least one element.
216      this.expectedValuesPerKey = max(expectedValuesPerKey, 1);
217
218      return this;
219    }
220
221    /**
222     * By default, if we are handed a value collection bigger than expectedValuesPerKey, presize to
223     * accept that many elements.
224     *
225     * <p>This gets overridden in ImmutableSetMultimap.Builder to only trust the size of {@code
226     * values} if it is a Set and therefore probably already deduplicated.
227     */
228    int expectedValueCollectionSize(int defaultExpectedValues, Iterable<?> values) {
229      if (values instanceof Collection<?>) {
230        Collection<?> collection = (Collection<?>) values;
231        return max(defaultExpectedValues, collection.size());
232      } else {
233        return defaultExpectedValues;
234      }
235    }
236
237    /** Adds a key-value mapping to the built multimap. */
238    @CanIgnoreReturnValue
239    public Builder<K, V> put(K key, V value) {
240      checkEntryNotNull(key, value);
241      ImmutableCollection.Builder<V> valuesBuilder = ensureBuilderMapNonNull().get(key);
242      if (valuesBuilder == null) {
243        valuesBuilder = newValueCollectionBuilderWithExpectedSize(expectedValuesPerKey);
244        ensureBuilderMapNonNull().put(key, valuesBuilder);
245      }
246      valuesBuilder.add(value);
247      return this;
248    }
249
250    /**
251     * Adds an entry to the built multimap.
252     *
253     * @since 11.0
254     */
255    @CanIgnoreReturnValue
256    public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
257      return put(entry.getKey(), entry.getValue());
258    }
259
260    /**
261     * Adds entries to the built multimap.
262     *
263     * @since 19.0
264     */
265    @CanIgnoreReturnValue
266    public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
267      for (Entry<? extends K, ? extends V> entry : entries) {
268        put(entry);
269      }
270      return this;
271    }
272
273    /**
274     * Stores a collection of values with the same key in the built multimap.
275     *
276     * @throws NullPointerException if {@code key}, {@code values}, or any element in {@code values}
277     *     is null. The builder is left in an invalid state.
278     */
279    @CanIgnoreReturnValue
280    public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
281      if (key == null) {
282        throw new NullPointerException("null key in entry: null=" + Iterables.toString(values));
283      }
284      Iterator<? extends V> valuesItr = values.iterator();
285      if (!valuesItr.hasNext()) {
286        return this;
287      }
288      ImmutableCollection.Builder<V> valuesBuilder = ensureBuilderMapNonNull().get(key);
289      if (valuesBuilder == null) {
290        valuesBuilder =
291            newValueCollectionBuilderWithExpectedSize(
292                expectedValueCollectionSize(expectedValuesPerKey, values));
293        ensureBuilderMapNonNull().put(key, valuesBuilder);
294      }
295      while (valuesItr.hasNext()) {
296        V value = valuesItr.next();
297        checkEntryNotNull(key, value);
298        valuesBuilder.add(value);
299      }
300      return this;
301    }
302
303    /**
304     * Stores an array of values with the same key in the built multimap.
305     *
306     * @throws NullPointerException if the key or any value is null. The builder is left in an
307     *     invalid state.
308     */
309    @CanIgnoreReturnValue
310    public Builder<K, V> putAll(K key, V... values) {
311      return putAll(key, asList(values));
312    }
313
314    /**
315     * Stores another multimap's entries in the built multimap. The generated multimap's key and
316     * value orderings correspond to the iteration ordering of the {@code multimap.asMap()} view,
317     * with new keys and values following any existing keys and values.
318     *
319     * @throws NullPointerException if any key or value in {@code multimap} is null. The builder is
320     *     left in an invalid state.
321     */
322    @CanIgnoreReturnValue
323    public Builder<K, V> putAll(Multimap<? extends K, ? extends V> multimap) {
324      for (Entry<? extends K, ? extends Collection<? extends V>> entry :
325          multimap.asMap().entrySet()) {
326        putAll(entry.getKey(), entry.getValue());
327      }
328      return this;
329    }
330
331    /**
332     * Specifies the ordering of the generated multimap's keys.
333     *
334     * @since 8.0
335     */
336    @CanIgnoreReturnValue
337    public Builder<K, V> orderKeysBy(Comparator<? super K> keyComparator) {
338      this.keyComparator = checkNotNull(keyComparator);
339      return this;
340    }
341
342    /**
343     * Specifies the ordering of the generated multimap's values for each key.
344     *
345     * @since 8.0
346     */
347    @CanIgnoreReturnValue
348    public Builder<K, V> orderValuesBy(Comparator<? super V> valueComparator) {
349      this.valueComparator = checkNotNull(valueComparator);
350      return this;
351    }
352
353    @CanIgnoreReturnValue
354    Builder<K, V> combine(Builder<K, V> other) {
355      if (other.builderMap != null) {
356        for (Map.Entry<K, ImmutableCollection.Builder<V>> entry : other.builderMap.entrySet()) {
357          putAll(entry.getKey(), entry.getValue().build());
358        }
359      }
360      return this;
361    }
362
363    /** Returns a newly-created immutable multimap. */
364    public ImmutableMultimap<K, V> build() {
365      if (builderMap == null) {
366        return ImmutableListMultimap.of();
367      }
368      Collection<Map.Entry<K, ImmutableCollection.Builder<V>>> mapEntries = builderMap.entrySet();
369      if (keyComparator != null) {
370        mapEntries = Ordering.from(keyComparator).<K>onKeys().immutableSortedCopy(mapEntries);
371      }
372      return ImmutableListMultimap.fromMapBuilderEntries(mapEntries, valueComparator);
373    }
374  }
375
376  /**
377   * Returns an immutable multimap containing the same mappings as {@code multimap}, in the
378   * "key-grouped" iteration order described in the class documentation.
379   *
380   * <p>Despite the method name, this method attempts to avoid actually copying the data when it is
381   * safe to do so. The exact circumstances under which a copy will or will not be performed are
382   * undocumented and subject to change.
383   *
384   * @throws NullPointerException if any key or value in {@code multimap} is null
385   */
386  public static <K, V> ImmutableMultimap<K, V> copyOf(Multimap<? extends K, ? extends V> multimap) {
387    if (multimap instanceof ImmutableMultimap) {
388      @SuppressWarnings("unchecked") // safe since multimap is not writable
389      ImmutableMultimap<K, V> kvMultimap = (ImmutableMultimap<K, V>) multimap;
390      if (!kvMultimap.isPartialView()) {
391        return kvMultimap;
392      }
393    }
394    return ImmutableListMultimap.copyOf(multimap);
395  }
396
397  /**
398   * Returns an immutable multimap containing the specified entries. The returned multimap iterates
399   * over keys in the order they were first encountered in the input, and the values for each key
400   * are iterated in the order they were encountered.
401   *
402   * @throws NullPointerException if any key, value, or entry is null
403   * @since 19.0
404   */
405  public static <K, V> ImmutableMultimap<K, V> copyOf(
406      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
407    return ImmutableListMultimap.copyOf(entries);
408  }
409
410  final transient ImmutableMap<K, ? extends ImmutableCollection<V>> map;
411  final transient int size;
412
413  ImmutableMultimap(ImmutableMap<K, ? extends ImmutableCollection<V>> map, int size) {
414    this.map = map;
415    this.size = size;
416  }
417
418  // mutators (not supported)
419
420  /**
421   * Guaranteed to throw an exception and leave the multimap unmodified.
422   *
423   * @throws UnsupportedOperationException always
424   * @deprecated Unsupported operation.
425   */
426  @CanIgnoreReturnValue
427  @Deprecated
428  @Override
429  @DoNotCall("Always throws UnsupportedOperationException")
430  // DoNotCall wants this to be final, but we want to override it to return more specific types.
431  // Inheritance is closed, and all subtypes are @DoNotCall, so this is safe to suppress.
432  @SuppressWarnings("DoNotCall")
433  public ImmutableCollection<V> removeAll(@Nullable Object key) {
434    throw new UnsupportedOperationException();
435  }
436
437  /**
438   * Guaranteed to throw an exception and leave the multimap unmodified.
439   *
440   * @throws UnsupportedOperationException always
441   * @deprecated Unsupported operation.
442   */
443  @CanIgnoreReturnValue
444  @Deprecated
445  @Override
446  @DoNotCall("Always throws UnsupportedOperationException")
447  // DoNotCall wants this to be final, but we want to override it to return more specific types.
448  // Inheritance is closed, and all subtypes are @DoNotCall, so this is safe to suppress.
449  @SuppressWarnings("DoNotCall")
450  public ImmutableCollection<V> replaceValues(K key, Iterable<? extends V> values) {
451    throw new UnsupportedOperationException();
452  }
453
454  /**
455   * Guaranteed to throw an exception and leave the multimap unmodified.
456   *
457   * @throws UnsupportedOperationException always
458   * @deprecated Unsupported operation.
459   */
460  @Deprecated
461  @Override
462  @DoNotCall("Always throws UnsupportedOperationException")
463  public final void clear() {
464    throw new UnsupportedOperationException();
465  }
466
467  /**
468   * Returns an immutable collection of the values for the given key. If no mappings in the multimap
469   * have the provided key, an empty immutable collection is returned. The values are in the same
470   * order as the parameters used to build this multimap.
471   */
472  @Override
473  public abstract ImmutableCollection<V> get(K key);
474
475  /**
476   * Returns an immutable multimap which is the inverse of this one. For every key-value mapping in
477   * the original, the result will have a mapping with key and value reversed.
478   *
479   * @since 11.0
480   */
481  public abstract ImmutableMultimap<V, K> inverse();
482
483  /**
484   * Guaranteed to throw an exception and leave the multimap unmodified.
485   *
486   * @throws UnsupportedOperationException always
487   * @deprecated Unsupported operation.
488   */
489  @CanIgnoreReturnValue
490  @Deprecated
491  @Override
492  @DoNotCall("Always throws UnsupportedOperationException")
493  public final boolean put(K key, V value) {
494    throw new UnsupportedOperationException();
495  }
496
497  /**
498   * Guaranteed to throw an exception and leave the multimap unmodified.
499   *
500   * @throws UnsupportedOperationException always
501   * @deprecated Unsupported operation.
502   */
503  @CanIgnoreReturnValue
504  @Deprecated
505  @Override
506  @DoNotCall("Always throws UnsupportedOperationException")
507  public final boolean putAll(K key, Iterable<? extends V> values) {
508    throw new UnsupportedOperationException();
509  }
510
511  /**
512   * Guaranteed to throw an exception and leave the multimap unmodified.
513   *
514   * @throws UnsupportedOperationException always
515   * @deprecated Unsupported operation.
516   */
517  @CanIgnoreReturnValue
518  @Deprecated
519  @Override
520  @DoNotCall("Always throws UnsupportedOperationException")
521  public final boolean putAll(Multimap<? extends K, ? extends V> multimap) {
522    throw new UnsupportedOperationException();
523  }
524
525  /**
526   * Guaranteed to throw an exception and leave the multimap unmodified.
527   *
528   * @throws UnsupportedOperationException always
529   * @deprecated Unsupported operation.
530   */
531  @CanIgnoreReturnValue
532  @Deprecated
533  @Override
534  @DoNotCall("Always throws UnsupportedOperationException")
535  public final boolean remove(@Nullable Object key, @Nullable Object value) {
536    throw new UnsupportedOperationException();
537  }
538
539  /**
540   * Returns {@code true} if this immutable multimap's implementation contains references to
541   * user-created objects that aren't accessible via this multimap's methods. This is generally used
542   * to determine whether {@code copyOf} implementations should make an explicit copy to avoid
543   * memory leaks.
544   */
545  final boolean isPartialView() {
546    return map.isPartialView();
547  }
548
549  // accessors
550
551  @Override
552  public /* TODO(cpovirk): final */ boolean containsKey(@Nullable Object key) {
553    return map.containsKey(key);
554  }
555
556  @Override
557  public final boolean containsValue(@Nullable Object value) {
558    return value != null && super.containsValue(value);
559  }
560
561  @Override
562  public final int size() {
563    return size;
564  }
565
566  // views
567
568  /**
569   * Returns an immutable set of the distinct keys in this multimap, in the same order as they
570   * appear in this multimap.
571   */
572  @Override
573  public /* TODO(cpovirk): final */ ImmutableSet<K> keySet() {
574    return map.keySet();
575  }
576
577  @Override
578  final Set<K> createKeySet() {
579    throw new AssertionError("unreachable");
580  }
581
582  /**
583   * Returns an immutable map that associates each key with its corresponding values in the
584   * multimap. Keys and values appear in the same order as in this multimap.
585   */
586  @Override
587  @SuppressWarnings("unchecked") // a widening cast
588  public ImmutableMap<K, Collection<V>> asMap() {
589    return (ImmutableMap) map;
590  }
591
592  @Override
593  final Map<K, Collection<V>> createAsMap() {
594    throw new AssertionError("should never be called");
595  }
596
597  /** Returns an immutable collection of all key-value pairs in the multimap. */
598  @Override
599  public ImmutableCollection<Entry<K, V>> entries() {
600    return (ImmutableCollection<Entry<K, V>>) super.entries();
601  }
602
603  @Override
604  final ImmutableCollection<Entry<K, V>> createEntries() {
605    return new EntryCollection<>(this);
606  }
607
608  private static final class EntryCollection<K, V> extends ImmutableCollection<Entry<K, V>> {
609    @Weak final ImmutableMultimap<K, V> multimap;
610
611    EntryCollection(ImmutableMultimap<K, V> multimap) {
612      this.multimap = multimap;
613    }
614
615    @Override
616    public UnmodifiableIterator<Entry<K, V>> iterator() {
617      return multimap.entryIterator();
618    }
619
620    @Override
621    boolean isPartialView() {
622      return multimap.isPartialView();
623    }
624
625    @Override
626    public int size() {
627      return multimap.size();
628    }
629
630    @Override
631    public boolean contains(@Nullable Object object) {
632      if (object instanceof Entry) {
633        Entry<?, ?> entry = (Entry<?, ?>) object;
634        return multimap.containsEntry(entry.getKey(), entry.getValue());
635      }
636      return false;
637    }
638
639    // redeclare to help optimizers with b/310253115
640    @SuppressWarnings("RedundantOverride")
641    @Override
642    @J2ktIncompatible
643    @GwtIncompatible
644        Object writeReplace() {
645      return super.writeReplace();
646    }
647
648    @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 0;
649  }
650
651  @Override
652  final UnmodifiableIterator<Entry<K, V>> entryIterator() {
653    return new UnmodifiableIterator<Entry<K, V>>() {
654      final Iterator<? extends Entry<K, ? extends ImmutableCollection<V>>> asMapItr =
655          map.entrySet().iterator();
656      @Nullable K currentKey = null;
657      Iterator<V> valueItr = emptyIterator();
658
659      @Override
660      public boolean hasNext() {
661        return valueItr.hasNext() || asMapItr.hasNext();
662      }
663
664      @Override
665      public Entry<K, V> next() {
666        if (!valueItr.hasNext()) {
667          Entry<K, ? extends ImmutableCollection<V>> entry = asMapItr.next();
668          currentKey = entry.getKey();
669          valueItr = entry.getValue().iterator();
670        }
671        /*
672         * requireNonNull is safe: The first call to this method always enters the !hasNext() case
673         * and populates currentKey, after which it's never cleared.
674         */
675        return immutableEntry(requireNonNull(currentKey), valueItr.next());
676      }
677    };
678  }
679
680  @Override
681  @GwtIncompatible // Spliterator
682  final Spliterator<Entry<K, V>> entrySpliterator() {
683    return CollectSpliterators.flatMap(
684        asMap().entrySet().spliterator(),
685        keyToValueCollectionEntry -> {
686          K key = keyToValueCollectionEntry.getKey();
687          Collection<V> valueCollection = keyToValueCollectionEntry.getValue();
688          return CollectSpliterators.map(
689              valueCollection.spliterator(),
690              Spliterator.ORDERED | Spliterator.NONNULL | Spliterator.IMMUTABLE,
691              (V value) -> immutableEntry(key, value));
692        },
693        Spliterator.SIZED | (this instanceof SetMultimap ? Spliterator.DISTINCT : 0),
694        size());
695  }
696
697  @Override
698  public final void forEach(BiConsumer<? super K, ? super V> action) {
699    checkNotNull(action);
700    asMap()
701        .forEach(
702            (key, valueCollection) -> valueCollection.forEach(value -> action.accept(key, value)));
703  }
704
705  /**
706   * Returns an immutable multiset containing all the keys in this multimap, in the same order and
707   * with the same frequencies as they appear in this multimap; to get only a single occurrence of
708   * each key, use {@link #keySet()}.
709   */
710  @Override
711  public final ImmutableMultiset<K> keys() {
712    return (ImmutableMultiset<K>) super.keys();
713  }
714
715  @Override
716  final ImmutableMultiset<K> createKeys() {
717    return new Keys();
718  }
719
720  @SuppressWarnings("serial") // Uses writeReplace, not default serialization
721  @WeakOuter
722  private final class Keys extends ImmutableMultiset<K> {
723    @Override
724    public boolean contains(@Nullable Object object) {
725      return containsKey(object);
726    }
727
728    @Override
729    public int count(@Nullable Object element) {
730      Collection<V> values = map.get(element);
731      return (values == null) ? 0 : values.size();
732    }
733
734    @Override
735    public ImmutableSet<K> elementSet() {
736      return keySet();
737    }
738
739    @Override
740    public int size() {
741      return ImmutableMultimap.this.size();
742    }
743
744    @Override
745    Multiset.Entry<K> getEntry(int index) {
746      Map.Entry<K, ? extends Collection<V>> entry = map.entrySet().asList().get(index);
747      return Multisets.immutableEntry(entry.getKey(), entry.getValue().size());
748    }
749
750    @Override
751    boolean isPartialView() {
752      return true;
753    }
754
755    @GwtIncompatible
756    @J2ktIncompatible
757    @Override
758    Object writeReplace() {
759      return new KeysSerializedForm(ImmutableMultimap.this);
760    }
761
762    @GwtIncompatible
763    @J2ktIncompatible
764    private void readObject(ObjectInputStream stream) throws InvalidObjectException {
765      throw new InvalidObjectException("Use KeysSerializedForm");
766    }
767  }
768
769  @GwtIncompatible
770  @J2ktIncompatible
771  private static final class KeysSerializedForm implements Serializable {
772    final ImmutableMultimap<?, ?> multimap;
773
774    KeysSerializedForm(ImmutableMultimap<?, ?> multimap) {
775      this.multimap = multimap;
776    }
777
778    Object readResolve() {
779      return multimap.keys();
780    }
781  }
782
783  /**
784   * Returns an immutable collection of the values in this multimap. Its iterator traverses the
785   * values for the first key, the values for the second key, and so on.
786   */
787  @Override
788  public /* TODO(cpovirk): final */ ImmutableCollection<V> values() {
789    return (ImmutableCollection<V>) super.values();
790  }
791
792  @Override
793  final ImmutableCollection<V> createValues() {
794    return new Values<>(this);
795  }
796
797  @Override
798  final UnmodifiableIterator<V> valueIterator() {
799    return new UnmodifiableIterator<V>() {
800      final Iterator<? extends ImmutableCollection<V>> valueCollectionItr = map.values().iterator();
801      Iterator<V> valueItr = emptyIterator();
802
803      @Override
804      public boolean hasNext() {
805        return valueItr.hasNext() || valueCollectionItr.hasNext();
806      }
807
808      @Override
809      public V next() {
810        if (!valueItr.hasNext()) {
811          valueItr = valueCollectionItr.next().iterator();
812        }
813        return valueItr.next();
814      }
815    };
816  }
817
818  private static final class Values<K, V> extends ImmutableCollection<V> {
819    @Weak private final transient ImmutableMultimap<K, V> multimap;
820
821    Values(ImmutableMultimap<K, V> multimap) {
822      this.multimap = multimap;
823    }
824
825    @Override
826    public boolean contains(@Nullable Object object) {
827      return multimap.containsValue(object);
828    }
829
830    @Override
831    public UnmodifiableIterator<V> iterator() {
832      return multimap.valueIterator();
833    }
834
835    @GwtIncompatible // not present in emulated superclass
836    @Override
837    int copyIntoArray(@Nullable Object[] dst, int offset) {
838      for (ImmutableCollection<V> valueCollection : multimap.map.values()) {
839        offset = valueCollection.copyIntoArray(dst, offset);
840      }
841      return offset;
842    }
843
844    @Override
845    public int size() {
846      return multimap.size();
847    }
848
849    @Override
850    boolean isPartialView() {
851      return true;
852    }
853
854    // redeclare to help optimizers with b/310253115
855    @SuppressWarnings("RedundantOverride")
856    @Override
857    @J2ktIncompatible
858    @GwtIncompatible
859        Object writeReplace() {
860      return super.writeReplace();
861    }
862
863    @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 0;
864  }
865
866  @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 0;
867}