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