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