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