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(emulated = true)
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   * <pre>{@code
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   * }</pre>
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  // These constants allow the deserialization code to set final fields. This
414  // holder class makes sure they are not initialized unless an instance is
415  // deserialized.
416  @GwtIncompatible // java serialization is not supported
417  @J2ktIncompatible
418  static class FieldSettersHolder {
419    static final Serialization.FieldSetter<? super ImmutableMultimap<?, ?>> MAP_FIELD_SETTER =
420        Serialization.getFieldSetter(ImmutableMultimap.class, "map");
421    static final Serialization.FieldSetter<? super ImmutableMultimap<?, ?>> SIZE_FIELD_SETTER =
422        Serialization.getFieldSetter(ImmutableMultimap.class, "size");
423  }
424
425  ImmutableMultimap(ImmutableMap<K, ? extends ImmutableCollection<V>> map, int size) {
426    this.map = map;
427    this.size = size;
428  }
429
430  // mutators (not supported)
431
432  /**
433   * Guaranteed to throw an exception and leave the multimap unmodified.
434   *
435   * @throws UnsupportedOperationException always
436   * @deprecated Unsupported operation.
437   */
438  @CanIgnoreReturnValue
439  @Deprecated
440  @Override
441  @DoNotCall("Always throws UnsupportedOperationException")
442  // DoNotCall wants this to be final, but we want to override it to return more specific types.
443  // Inheritance is closed, and all subtypes are @DoNotCall, so this is safe to suppress.
444  @SuppressWarnings("DoNotCall")
445  public ImmutableCollection<V> removeAll(@Nullable Object key) {
446    throw new UnsupportedOperationException();
447  }
448
449  /**
450   * Guaranteed to throw an exception and leave the multimap unmodified.
451   *
452   * @throws UnsupportedOperationException always
453   * @deprecated Unsupported operation.
454   */
455  @CanIgnoreReturnValue
456  @Deprecated
457  @Override
458  @DoNotCall("Always throws UnsupportedOperationException")
459  // DoNotCall wants this to be final, but we want to override it to return more specific types.
460  // Inheritance is closed, and all subtypes are @DoNotCall, so this is safe to suppress.
461  @SuppressWarnings("DoNotCall")
462  public ImmutableCollection<V> replaceValues(K key, Iterable<? extends V> values) {
463    throw new UnsupportedOperationException();
464  }
465
466  /**
467   * Guaranteed to throw an exception and leave the multimap unmodified.
468   *
469   * @throws UnsupportedOperationException always
470   * @deprecated Unsupported operation.
471   */
472  @Deprecated
473  @Override
474  @DoNotCall("Always throws UnsupportedOperationException")
475  public final void clear() {
476    throw new UnsupportedOperationException();
477  }
478
479  /**
480   * Returns an immutable collection of the values for the given key. If no mappings in the multimap
481   * have the provided key, an empty immutable collection is returned. The values are in the same
482   * order as the parameters used to build this multimap.
483   */
484  @Override
485  public abstract ImmutableCollection<V> get(K key);
486
487  /**
488   * Returns an immutable multimap which is the inverse of this one. For every key-value mapping in
489   * the original, the result will have a mapping with key and value reversed.
490   *
491   * @since 11.0
492   */
493  public abstract ImmutableMultimap<V, K> inverse();
494
495  /**
496   * Guaranteed to throw an exception and leave the multimap unmodified.
497   *
498   * @throws UnsupportedOperationException always
499   * @deprecated Unsupported operation.
500   */
501  @CanIgnoreReturnValue
502  @Deprecated
503  @Override
504  @DoNotCall("Always throws UnsupportedOperationException")
505  public final boolean put(K key, V value) {
506    throw new UnsupportedOperationException();
507  }
508
509  /**
510   * Guaranteed to throw an exception and leave the multimap unmodified.
511   *
512   * @throws UnsupportedOperationException always
513   * @deprecated Unsupported operation.
514   */
515  @CanIgnoreReturnValue
516  @Deprecated
517  @Override
518  @DoNotCall("Always throws UnsupportedOperationException")
519  public final boolean putAll(K key, Iterable<? extends V> values) {
520    throw new UnsupportedOperationException();
521  }
522
523  /**
524   * Guaranteed to throw an exception and leave the multimap unmodified.
525   *
526   * @throws UnsupportedOperationException always
527   * @deprecated Unsupported operation.
528   */
529  @CanIgnoreReturnValue
530  @Deprecated
531  @Override
532  @DoNotCall("Always throws UnsupportedOperationException")
533  public final boolean putAll(Multimap<? extends K, ? extends V> multimap) {
534    throw new UnsupportedOperationException();
535  }
536
537  /**
538   * Guaranteed to throw an exception and leave the multimap unmodified.
539   *
540   * @throws UnsupportedOperationException always
541   * @deprecated Unsupported operation.
542   */
543  @CanIgnoreReturnValue
544  @Deprecated
545  @Override
546  @DoNotCall("Always throws UnsupportedOperationException")
547  public final boolean remove(@Nullable Object key, @Nullable Object value) {
548    throw new UnsupportedOperationException();
549  }
550
551  /**
552   * Returns {@code true} if this immutable multimap's implementation contains references to
553   * user-created objects that aren't accessible via this multimap's methods. This is generally used
554   * to determine whether {@code copyOf} implementations should make an explicit copy to avoid
555   * memory leaks.
556   */
557  boolean isPartialView() {
558    return map.isPartialView();
559  }
560
561  // accessors
562
563  @Override
564  public boolean containsKey(@Nullable Object key) {
565    return map.containsKey(key);
566  }
567
568  @Override
569  public boolean containsValue(@Nullable Object value) {
570    return value != null && super.containsValue(value);
571  }
572
573  @Override
574  public int size() {
575    return size;
576  }
577
578  // views
579
580  /**
581   * Returns an immutable set of the distinct keys in this multimap, in the same order as they
582   * appear in this multimap.
583   */
584  @Override
585  public ImmutableSet<K> keySet() {
586    return map.keySet();
587  }
588
589  @Override
590  Set<K> createKeySet() {
591    throw new AssertionError("unreachable");
592  }
593
594  /**
595   * Returns an immutable map that associates each key with its corresponding values in the
596   * multimap. Keys and values appear in the same order as in this multimap.
597   */
598  @Override
599  @SuppressWarnings("unchecked") // a widening cast
600  public ImmutableMap<K, Collection<V>> asMap() {
601    return (ImmutableMap) map;
602  }
603
604  @Override
605  Map<K, Collection<V>> createAsMap() {
606    throw new AssertionError("should never be called");
607  }
608
609  /** Returns an immutable collection of all key-value pairs in the multimap. */
610  @Override
611  public ImmutableCollection<Entry<K, V>> entries() {
612    return (ImmutableCollection<Entry<K, V>>) super.entries();
613  }
614
615  @Override
616  ImmutableCollection<Entry<K, V>> createEntries() {
617    return new EntryCollection<>(this);
618  }
619
620  private static class EntryCollection<K, V> extends ImmutableCollection<Entry<K, V>> {
621    @Weak final ImmutableMultimap<K, V> multimap;
622
623    EntryCollection(ImmutableMultimap<K, V> multimap) {
624      this.multimap = multimap;
625    }
626
627    @Override
628    public UnmodifiableIterator<Entry<K, V>> iterator() {
629      return multimap.entryIterator();
630    }
631
632    @Override
633    boolean isPartialView() {
634      return multimap.isPartialView();
635    }
636
637    @Override
638    public int size() {
639      return multimap.size();
640    }
641
642    @Override
643    public boolean contains(@Nullable Object object) {
644      if (object instanceof Entry) {
645        Entry<?, ?> entry = (Entry<?, ?>) object;
646        return multimap.containsEntry(entry.getKey(), entry.getValue());
647      }
648      return false;
649    }
650
651    // redeclare to help optimizers with b/310253115
652    @SuppressWarnings("RedundantOverride")
653    @Override
654    @J2ktIncompatible // serialization
655    @GwtIncompatible // serialization
656    Object writeReplace() {
657      return super.writeReplace();
658    }
659
660    private static final long serialVersionUID = 0;
661  }
662
663  @Override
664  UnmodifiableIterator<Entry<K, V>> entryIterator() {
665    return new UnmodifiableIterator<Entry<K, V>>() {
666      final Iterator<? extends Entry<K, ? extends ImmutableCollection<V>>> asMapItr =
667          map.entrySet().iterator();
668      @Nullable K currentKey = null;
669      Iterator<V> valueItr = emptyIterator();
670
671      @Override
672      public boolean hasNext() {
673        return valueItr.hasNext() || asMapItr.hasNext();
674      }
675
676      @Override
677      public Entry<K, V> next() {
678        if (!valueItr.hasNext()) {
679          Entry<K, ? extends ImmutableCollection<V>> entry = asMapItr.next();
680          currentKey = entry.getKey();
681          valueItr = entry.getValue().iterator();
682        }
683        /*
684         * requireNonNull is safe: The first call to this method always enters the !hasNext() case
685         * and populates currentKey, after which it's never cleared.
686         */
687        return immutableEntry(requireNonNull(currentKey), valueItr.next());
688      }
689    };
690  }
691
692  @Override
693  Spliterator<Entry<K, V>> entrySpliterator() {
694    return CollectSpliterators.flatMap(
695        asMap().entrySet().spliterator(),
696        keyToValueCollectionEntry -> {
697          K key = keyToValueCollectionEntry.getKey();
698          Collection<V> valueCollection = keyToValueCollectionEntry.getValue();
699          return CollectSpliterators.map(
700              valueCollection.spliterator(), (V value) -> immutableEntry(key, value));
701        },
702        Spliterator.SIZED | (this instanceof SetMultimap ? Spliterator.DISTINCT : 0),
703        size());
704  }
705
706  @Override
707  public void forEach(BiConsumer<? super K, ? super V> action) {
708    checkNotNull(action);
709    asMap()
710        .forEach(
711            (key, valueCollection) -> valueCollection.forEach(value -> action.accept(key, value)));
712  }
713
714  /**
715   * Returns an immutable multiset containing all the keys in this multimap, in the same order and
716   * with the same frequencies as they appear in this multimap; to get only a single occurrence of
717   * each key, use {@link #keySet}.
718   */
719  @Override
720  public ImmutableMultiset<K> keys() {
721    return (ImmutableMultiset<K>) super.keys();
722  }
723
724  @Override
725  ImmutableMultiset<K> createKeys() {
726    return new Keys();
727  }
728
729  @SuppressWarnings("serial") // Uses writeReplace, not default serialization
730  @WeakOuter
731  class Keys extends ImmutableMultiset<K> {
732    @Override
733    public boolean contains(@Nullable Object object) {
734      return containsKey(object);
735    }
736
737    @Override
738    public int count(@Nullable Object element) {
739      Collection<V> values = map.get(element);
740      return (values == null) ? 0 : values.size();
741    }
742
743    @Override
744    public ImmutableSet<K> elementSet() {
745      return keySet();
746    }
747
748    @Override
749    public int size() {
750      return ImmutableMultimap.this.size();
751    }
752
753    @Override
754    Multiset.Entry<K> getEntry(int index) {
755      Map.Entry<K, ? extends Collection<V>> entry = map.entrySet().asList().get(index);
756      return Multisets.immutableEntry(entry.getKey(), entry.getValue().size());
757    }
758
759    @Override
760    boolean isPartialView() {
761      return true;
762    }
763
764    @GwtIncompatible
765    @J2ktIncompatible
766    @Override
767    Object writeReplace() {
768      return new KeysSerializedForm(ImmutableMultimap.this);
769    }
770
771    @GwtIncompatible
772    @J2ktIncompatible
773    private void readObject(ObjectInputStream stream) throws InvalidObjectException {
774      throw new InvalidObjectException("Use KeysSerializedForm");
775    }
776  }
777
778  @GwtIncompatible
779  @J2ktIncompatible
780  private static final class KeysSerializedForm implements Serializable {
781    final ImmutableMultimap<?, ?> multimap;
782
783    KeysSerializedForm(ImmutableMultimap<?, ?> multimap) {
784      this.multimap = multimap;
785    }
786
787    Object readResolve() {
788      return multimap.keys();
789    }
790  }
791
792  /**
793   * Returns an immutable collection of the values in this multimap. Its iterator traverses the
794   * values for the first key, the values for the second key, and so on.
795   */
796  @Override
797  public ImmutableCollection<V> values() {
798    return (ImmutableCollection<V>) super.values();
799  }
800
801  @Override
802  ImmutableCollection<V> createValues() {
803    return new Values<>(this);
804  }
805
806  @Override
807  UnmodifiableIterator<V> valueIterator() {
808    return new UnmodifiableIterator<V>() {
809      Iterator<? extends ImmutableCollection<V>> valueCollectionItr = map.values().iterator();
810      Iterator<V> valueItr = emptyIterator();
811
812      @Override
813      public boolean hasNext() {
814        return valueItr.hasNext() || valueCollectionItr.hasNext();
815      }
816
817      @Override
818      public V next() {
819        if (!valueItr.hasNext()) {
820          valueItr = valueCollectionItr.next().iterator();
821        }
822        return valueItr.next();
823      }
824    };
825  }
826
827  private static final class Values<K, V> extends ImmutableCollection<V> {
828    @Weak private final transient ImmutableMultimap<K, V> multimap;
829
830    Values(ImmutableMultimap<K, V> multimap) {
831      this.multimap = multimap;
832    }
833
834    @Override
835    public boolean contains(@Nullable Object object) {
836      return multimap.containsValue(object);
837    }
838
839    @Override
840    public UnmodifiableIterator<V> iterator() {
841      return multimap.valueIterator();
842    }
843
844    @GwtIncompatible // not present in emulated superclass
845    @Override
846    int copyIntoArray(@Nullable Object[] dst, int offset) {
847      for (ImmutableCollection<V> valueCollection : multimap.map.values()) {
848        offset = valueCollection.copyIntoArray(dst, offset);
849      }
850      return offset;
851    }
852
853    @Override
854    public int size() {
855      return multimap.size();
856    }
857
858    @Override
859    boolean isPartialView() {
860      return true;
861    }
862
863    // redeclare to help optimizers with b/310253115
864    @SuppressWarnings("RedundantOverride")
865    @Override
866    @J2ktIncompatible // serialization
867    @GwtIncompatible // serialization
868    Object writeReplace() {
869      return super.writeReplace();
870    }
871
872    @J2ktIncompatible // serialization
873    private static final long serialVersionUID = 0;
874  }
875
876  @J2ktIncompatible // serialization
877  private static final long serialVersionUID = 0;
878}