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