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.base.Preconditions.checkState; 021import static com.google.common.collect.CollectPreconditions.checkEntryNotNull; 022import static com.google.common.collect.CollectPreconditions.checkNonnegative; 023 024import com.google.common.annotations.Beta; 025import com.google.common.annotations.GwtCompatible; 026import com.google.common.annotations.VisibleForTesting; 027import com.google.errorprone.annotations.CanIgnoreReturnValue; 028import com.google.errorprone.annotations.DoNotCall; 029import com.google.errorprone.annotations.DoNotMock; 030import com.google.errorprone.annotations.concurrent.LazyInit; 031import com.google.j2objc.annotations.RetainedWith; 032import com.google.j2objc.annotations.WeakOuter; 033import java.io.Serializable; 034import java.util.AbstractMap; 035import java.util.Arrays; 036import java.util.Collection; 037import java.util.Collections; 038import java.util.Comparator; 039import java.util.EnumMap; 040import java.util.Iterator; 041import java.util.Map; 042import java.util.SortedMap; 043import java.util.Spliterator; 044import java.util.Spliterators; 045import java.util.function.BiFunction; 046import java.util.function.BinaryOperator; 047import java.util.function.Function; 048import java.util.stream.Collector; 049import java.util.stream.Collectors; 050import org.checkerframework.checker.nullness.qual.Nullable; 051 052/** 053 * A {@link Map} whose contents will never change, with many other important properties detailed at 054 * {@link ImmutableCollection}. 055 * 056 * <p>See the Guava User Guide article on <a href= 057 * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained"> immutable collections</a>. 058 * 059 * @author Jesse Wilson 060 * @author Kevin Bourrillion 061 * @since 2.0 062 */ 063@DoNotMock("Use ImmutableMap.of or another implementation") 064@GwtCompatible(serializable = true, emulated = true) 065@SuppressWarnings("serial") // we're overriding default serialization 066public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable { 067 068 /** 069 * Returns a {@link Collector} that accumulates elements into an {@code ImmutableMap} whose keys 070 * and values are the result of applying the provided mapping functions to the input elements. 071 * Entries appear in the result {@code ImmutableMap} in encounter order. 072 * 073 * <p>If the mapped keys contain duplicates (according to {@link Object#equals(Object)}, an {@code 074 * IllegalArgumentException} is thrown when the collection operation is performed. (This differs 075 * from the {@code Collector} returned by {@link Collectors#toMap(Function, Function)}, which 076 * throws an {@code IllegalStateException}.) 077 * 078 * @since 21.0 079 */ 080 public static <T, K, V> Collector<T, ?, ImmutableMap<K, V>> toImmutableMap( 081 Function<? super T, ? extends K> keyFunction, 082 Function<? super T, ? extends V> valueFunction) { 083 return CollectCollectors.toImmutableMap(keyFunction, valueFunction); 084 } 085 086 /** 087 * Returns a {@link Collector} that accumulates elements into an {@code ImmutableMap} whose keys 088 * and values are the result of applying the provided mapping functions to the input elements. 089 * 090 * <p>If the mapped keys contain duplicates (according to {@link Object#equals(Object)}), the 091 * values are merged using the specified merging function. Entries will appear in the encounter 092 * order of the first occurrence of the key. 093 * 094 * @since 21.0 095 */ 096 public static <T, K, V> Collector<T, ?, ImmutableMap<K, V>> toImmutableMap( 097 Function<? super T, ? extends K> keyFunction, 098 Function<? super T, ? extends V> valueFunction, 099 BinaryOperator<V> mergeFunction) { 100 return CollectCollectors.toImmutableMap(keyFunction, valueFunction, mergeFunction); 101 } 102 103 /** 104 * Returns the empty map. This map behaves and performs comparably to {@link 105 * Collections#emptyMap}, and is preferable mainly for consistency and maintainability of your 106 * code. 107 */ 108 @SuppressWarnings("unchecked") 109 public static <K, V> ImmutableMap<K, V> of() { 110 return (ImmutableMap<K, V>) RegularImmutableMap.EMPTY; 111 } 112 113 /** 114 * Returns an immutable map containing a single entry. This map behaves and performs comparably to 115 * {@link Collections#singletonMap} but will not accept a null key or value. It is preferable 116 * mainly for consistency and maintainability of your code. 117 */ 118 public static <K, V> ImmutableMap<K, V> of(K k1, V v1) { 119 return ImmutableBiMap.of(k1, v1); 120 } 121 122 /** 123 * Returns an immutable map containing the given entries, in order. 124 * 125 * @throws IllegalArgumentException if duplicate keys are provided 126 */ 127 public static <K, V> ImmutableMap<K, V> of(K k1, V v1, K k2, V v2) { 128 return RegularImmutableMap.fromEntries(entryOf(k1, v1), entryOf(k2, v2)); 129 } 130 131 /** 132 * Returns an immutable map containing the given entries, in order. 133 * 134 * @throws IllegalArgumentException if duplicate keys are provided 135 */ 136 public static <K, V> ImmutableMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) { 137 return RegularImmutableMap.fromEntries(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3)); 138 } 139 140 /** 141 * Returns an immutable map containing the given entries, in order. 142 * 143 * @throws IllegalArgumentException if duplicate keys are provided 144 */ 145 public static <K, V> ImmutableMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { 146 return RegularImmutableMap.fromEntries( 147 entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4)); 148 } 149 150 /** 151 * Returns an immutable map containing the given entries, in order. 152 * 153 * @throws IllegalArgumentException if duplicate keys are provided 154 */ 155 public static <K, V> ImmutableMap<K, V> of( 156 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { 157 return RegularImmutableMap.fromEntries( 158 entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5)); 159 } 160 161 // looking for of() with > 5 entries? Use the builder instead. 162 163 /** 164 * Verifies that {@code key} and {@code value} are non-null, and returns a new immutable entry 165 * with those values. 166 * 167 * <p>A call to {@link Entry#setValue} on the returned entry will always throw {@link 168 * UnsupportedOperationException}. 169 */ 170 static <K, V> Entry<K, V> entryOf(K key, V value) { 171 checkEntryNotNull(key, value); 172 return new AbstractMap.SimpleImmutableEntry<>(key, value); 173 } 174 175 /** 176 * Returns a new builder. The generated builder is equivalent to the builder created by the {@link 177 * Builder} constructor. 178 */ 179 public static <K, V> Builder<K, V> builder() { 180 return new Builder<>(); 181 } 182 183 /** 184 * Returns a new builder, expecting the specified number of entries to be added. 185 * 186 * <p>If {@code expectedSize} is exactly the number of entries added to the builder before {@link 187 * Builder#build} is called, the builder is likely to perform better than an unsized {@link 188 * #builder()} would have. 189 * 190 * <p>It is not specified if any performance benefits apply if {@code expectedSize} is close to, 191 * but not exactly, the number of entries added to the builder. 192 * 193 * @since 23.1 194 */ 195 @Beta 196 public static <K, V> Builder<K, V> builderWithExpectedSize(int expectedSize) { 197 checkNonnegative(expectedSize, "expectedSize"); 198 return new Builder<>(expectedSize); 199 } 200 201 static void checkNoConflict( 202 boolean safe, String conflictDescription, Entry<?, ?> entry1, Entry<?, ?> entry2) { 203 if (!safe) { 204 throw conflictException(conflictDescription, entry1, entry2); 205 } 206 } 207 208 static IllegalArgumentException conflictException( 209 String conflictDescription, Object entry1, Object entry2) { 210 return new IllegalArgumentException( 211 "Multiple entries with same " + conflictDescription + ": " + entry1 + " and " + entry2); 212 } 213 214 /** 215 * A builder for creating immutable map instances, especially {@code public static final} maps 216 * ("constant maps"). Example: 217 * 218 * <pre>{@code 219 * static final ImmutableMap<String, Integer> WORD_TO_INT = 220 * new ImmutableMap.Builder<String, Integer>() 221 * .put("one", 1) 222 * .put("two", 2) 223 * .put("three", 3) 224 * .build(); 225 * }</pre> 226 * 227 * <p>For <i>small</i> immutable maps, the {@code ImmutableMap.of()} methods are even more 228 * convenient. 229 * 230 * <p>By default, a {@code Builder} will generate maps that iterate over entries in the order they 231 * were inserted into the builder, equivalently to {@code LinkedHashMap}. For example, in the 232 * above example, {@code WORD_TO_INT.entrySet()} is guaranteed to iterate over the entries in the 233 * order {@code "one"=1, "two"=2, "three"=3}, and {@code keySet()} and {@code values()} respect 234 * the same order. If you want a different order, consider using {@link ImmutableSortedMap} to 235 * sort by keys, or call {@link #orderEntriesByValue(Comparator)}, which changes this builder to 236 * sort entries by value. 237 * 238 * <p>Builder instances can be reused - it is safe to call {@link #build} multiple times to build 239 * multiple maps in series. Each map is a superset of the maps created before it. 240 * 241 * @since 2.0 242 */ 243 @DoNotMock 244 public static class Builder<K, V> { 245 @Nullable Comparator<? super V> valueComparator; 246 Entry<K, V>[] entries; 247 int size; 248 boolean entriesUsed; 249 250 /** 251 * Creates a new builder. The returned builder is equivalent to the builder generated by {@link 252 * ImmutableMap#builder}. 253 */ 254 public Builder() { 255 this(ImmutableCollection.Builder.DEFAULT_INITIAL_CAPACITY); 256 } 257 258 @SuppressWarnings("unchecked") 259 Builder(int initialCapacity) { 260 this.entries = new Entry[initialCapacity]; 261 this.size = 0; 262 this.entriesUsed = false; 263 } 264 265 private void ensureCapacity(int minCapacity) { 266 if (minCapacity > entries.length) { 267 entries = 268 Arrays.copyOf( 269 entries, ImmutableCollection.Builder.expandedCapacity(entries.length, minCapacity)); 270 entriesUsed = false; 271 } 272 } 273 274 /** 275 * Associates {@code key} with {@code value} in the built map. Duplicate keys are not allowed, 276 * and will cause {@link #build} to fail. 277 */ 278 @CanIgnoreReturnValue 279 public Builder<K, V> put(K key, V value) { 280 ensureCapacity(size + 1); 281 Entry<K, V> entry = entryOf(key, value); 282 // don't inline this: we want to fail atomically if key or value is null 283 entries[size++] = entry; 284 return this; 285 } 286 287 /** 288 * Adds the given {@code entry} to the map, making it immutable if necessary. Duplicate keys are 289 * not allowed, and will cause {@link #build} to fail. 290 * 291 * @since 11.0 292 */ 293 @CanIgnoreReturnValue 294 public Builder<K, V> put(Entry<? extends K, ? extends V> entry) { 295 return put(entry.getKey(), entry.getValue()); 296 } 297 298 /** 299 * Associates all of the given map's keys and values in the built map. Duplicate keys are not 300 * allowed, and will cause {@link #build} to fail. 301 * 302 * @throws NullPointerException if any key or value in {@code map} is null 303 */ 304 @CanIgnoreReturnValue 305 public Builder<K, V> putAll(Map<? extends K, ? extends V> map) { 306 return putAll(map.entrySet()); 307 } 308 309 /** 310 * Adds all of the given entries to the built map. Duplicate keys are not allowed, and will 311 * cause {@link #build} to fail. 312 * 313 * @throws NullPointerException if any key, value, or entry is null 314 * @since 19.0 315 */ 316 @CanIgnoreReturnValue 317 @Beta 318 public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) { 319 if (entries instanceof Collection) { 320 ensureCapacity(size + ((Collection<?>) entries).size()); 321 } 322 for (Entry<? extends K, ? extends V> entry : entries) { 323 put(entry); 324 } 325 return this; 326 } 327 328 /** 329 * Configures this {@code Builder} to order entries by value according to the specified 330 * comparator. 331 * 332 * <p>The sort order is stable, that is, if two entries have values that compare as equivalent, 333 * the entry that was inserted first will be first in the built map's iteration order. 334 * 335 * @throws IllegalStateException if this method was already called 336 * @since 19.0 337 */ 338 @CanIgnoreReturnValue 339 @Beta 340 public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) { 341 checkState(this.valueComparator == null, "valueComparator was already set"); 342 this.valueComparator = checkNotNull(valueComparator, "valueComparator"); 343 return this; 344 } 345 346 @CanIgnoreReturnValue 347 Builder<K, V> combine(Builder<K, V> other) { 348 checkNotNull(other); 349 ensureCapacity(this.size + other.size); 350 System.arraycopy(other.entries, 0, this.entries, this.size, other.size); 351 this.size += other.size; 352 return this; 353 } 354 355 /* 356 * TODO(kevinb): Should build() and the ImmutableBiMap & ImmutableSortedMap 357 * versions throw an IllegalStateException instead? 358 */ 359 360 /** 361 * Returns a newly-created immutable map. The iteration order of the returned map is the order 362 * in which entries were inserted into the builder, unless {@link #orderEntriesByValue} was 363 * called, in which case entries are sorted by value. 364 * 365 * @throws IllegalArgumentException if duplicate keys were added 366 */ 367 public ImmutableMap<K, V> build() { 368 /* 369 * If entries is full, or if hash flooding is detected, then this implementation may end up 370 * using the entries array directly and writing over the entry objects with non-terminal 371 * entries, but this is safe; if this Builder is used further, it will grow the entries array 372 * (so it can't affect the original array), and future build() calls will always copy any 373 * entry objects that cannot be safely reused. 374 */ 375 if (valueComparator != null) { 376 if (entriesUsed) { 377 entries = Arrays.copyOf(entries, size); 378 } 379 Arrays.sort( 380 entries, 0, size, Ordering.from(valueComparator).onResultOf(Maps.<V>valueFunction())); 381 } 382 switch (size) { 383 case 0: 384 return of(); 385 case 1: 386 return of(entries[0].getKey(), entries[0].getValue()); 387 default: 388 entriesUsed = true; 389 return RegularImmutableMap.fromEntryArray(size, entries); 390 } 391 } 392 393 @VisibleForTesting // only for testing JDK backed implementation 394 ImmutableMap<K, V> buildJdkBacked() { 395 checkState( 396 valueComparator == null, "buildJdkBacked is only for testing; can't use valueComparator"); 397 switch (size) { 398 case 0: 399 return of(); 400 case 1: 401 return of(entries[0].getKey(), entries[0].getValue()); 402 default: 403 entriesUsed = true; 404 return JdkBackedImmutableMap.create(size, entries); 405 } 406 } 407 } 408 409 /** 410 * Returns an immutable map containing the same entries as {@code map}. The returned map iterates 411 * over entries in the same order as the {@code entrySet} of the original map. If {@code map} 412 * somehow contains entries with duplicate keys (for example, if it is a {@code SortedMap} whose 413 * comparator is not <i>consistent with equals</i>), the results of this method are undefined. 414 * 415 * <p>Despite the method name, this method attempts to avoid actually copying the data when it is 416 * safe to do so. The exact circumstances under which a copy will or will not be performed are 417 * undocumented and subject to change. 418 * 419 * @throws NullPointerException if any key or value in {@code map} is null 420 */ 421 public static <K, V> ImmutableMap<K, V> copyOf(Map<? extends K, ? extends V> map) { 422 if ((map instanceof ImmutableMap) && !(map instanceof SortedMap)) { 423 @SuppressWarnings("unchecked") // safe since map is not writable 424 ImmutableMap<K, V> kvMap = (ImmutableMap<K, V>) map; 425 if (!kvMap.isPartialView()) { 426 return kvMap; 427 } 428 } else if (map instanceof EnumMap) { 429 @SuppressWarnings("unchecked") // safe since map is not writable 430 ImmutableMap<K, V> kvMap = (ImmutableMap<K, V>) copyOfEnumMap((EnumMap<?, ?>) map); 431 return kvMap; 432 } 433 return copyOf(map.entrySet()); 434 } 435 436 /** 437 * Returns an immutable map containing the specified entries. The returned map iterates over 438 * entries in the same order as the original iterable. 439 * 440 * @throws NullPointerException if any key, value, or entry is null 441 * @throws IllegalArgumentException if two entries have the same key 442 * @since 19.0 443 */ 444 @Beta 445 public static <K, V> ImmutableMap<K, V> copyOf( 446 Iterable<? extends Entry<? extends K, ? extends V>> entries) { 447 @SuppressWarnings("unchecked") // we'll only be using getKey and getValue, which are covariant 448 Entry<K, V>[] entryArray = (Entry<K, V>[]) Iterables.toArray(entries, EMPTY_ENTRY_ARRAY); 449 switch (entryArray.length) { 450 case 0: 451 return of(); 452 case 1: 453 Entry<K, V> onlyEntry = entryArray[0]; 454 return of(onlyEntry.getKey(), onlyEntry.getValue()); 455 default: 456 /* 457 * The current implementation will end up using entryArray directly, though it will write 458 * over the (arbitrary, potentially mutable) Entry objects actually stored in entryArray. 459 */ 460 return RegularImmutableMap.fromEntries(entryArray); 461 } 462 } 463 464 private static <K extends Enum<K>, V> ImmutableMap<K, V> copyOfEnumMap( 465 EnumMap<K, ? extends V> original) { 466 EnumMap<K, V> copy = new EnumMap<>(original); 467 for (Entry<?, ?> entry : copy.entrySet()) { 468 checkEntryNotNull(entry.getKey(), entry.getValue()); 469 } 470 return ImmutableEnumMap.asImmutable(copy); 471 } 472 473 static final Entry<?, ?>[] EMPTY_ENTRY_ARRAY = new Entry<?, ?>[0]; 474 475 abstract static class IteratorBasedImmutableMap<K, V> extends ImmutableMap<K, V> { 476 abstract UnmodifiableIterator<Entry<K, V>> entryIterator(); 477 478 Spliterator<Entry<K, V>> entrySpliterator() { 479 return Spliterators.spliterator( 480 entryIterator(), 481 size(), 482 Spliterator.DISTINCT | Spliterator.NONNULL | Spliterator.IMMUTABLE | Spliterator.ORDERED); 483 } 484 485 @Override 486 ImmutableSet<K> createKeySet() { 487 return new ImmutableMapKeySet<>(this); 488 } 489 490 @Override 491 ImmutableSet<Entry<K, V>> createEntrySet() { 492 class EntrySetImpl extends ImmutableMapEntrySet<K, V> { 493 @Override 494 ImmutableMap<K, V> map() { 495 return IteratorBasedImmutableMap.this; 496 } 497 498 @Override 499 public UnmodifiableIterator<Entry<K, V>> iterator() { 500 return entryIterator(); 501 } 502 } 503 return new EntrySetImpl(); 504 } 505 506 @Override 507 ImmutableCollection<V> createValues() { 508 return new ImmutableMapValues<>(this); 509 } 510 } 511 512 ImmutableMap() {} 513 514 /** 515 * Guaranteed to throw an exception and leave the map unmodified. 516 * 517 * @throws UnsupportedOperationException always 518 * @deprecated Unsupported operation. 519 */ 520 @CanIgnoreReturnValue 521 @Deprecated 522 @Override 523 @DoNotCall("Always throws UnsupportedOperationException") 524 public final V put(K k, V v) { 525 throw new UnsupportedOperationException(); 526 } 527 528 /** 529 * Guaranteed to throw an exception and leave the map unmodified. 530 * 531 * @throws UnsupportedOperationException always 532 * @deprecated Unsupported operation. 533 */ 534 @CanIgnoreReturnValue 535 @Deprecated 536 @Override 537 @DoNotCall("Always throws UnsupportedOperationException") 538 public final V putIfAbsent(K key, V value) { 539 throw new UnsupportedOperationException(); 540 } 541 542 /** 543 * Guaranteed to throw an exception and leave the map unmodified. 544 * 545 * @throws UnsupportedOperationException always 546 * @deprecated Unsupported operation. 547 */ 548 @Deprecated 549 @Override 550 @DoNotCall("Always throws UnsupportedOperationException") 551 public final boolean replace(K key, V oldValue, V newValue) { 552 throw new UnsupportedOperationException(); 553 } 554 555 /** 556 * Guaranteed to throw an exception and leave the map unmodified. 557 * 558 * @throws UnsupportedOperationException always 559 * @deprecated Unsupported operation. 560 */ 561 @Deprecated 562 @Override 563 @DoNotCall("Always throws UnsupportedOperationException") 564 public final V replace(K key, V value) { 565 throw new UnsupportedOperationException(); 566 } 567 568 /** 569 * Guaranteed to throw an exception and leave the map unmodified. 570 * 571 * @throws UnsupportedOperationException always 572 * @deprecated Unsupported operation. 573 */ 574 @Deprecated 575 @Override 576 @DoNotCall("Always throws UnsupportedOperationException") 577 public final V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) { 578 throw new UnsupportedOperationException(); 579 } 580 581 /** 582 * Guaranteed to throw an exception and leave the map unmodified. 583 * 584 * @throws UnsupportedOperationException always 585 * @deprecated Unsupported operation. 586 */ 587 @Deprecated 588 @Override 589 @DoNotCall("Always throws UnsupportedOperationException") 590 public final V computeIfPresent( 591 K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { 592 throw new UnsupportedOperationException(); 593 } 594 595 /** 596 * Guaranteed to throw an exception and leave the map unmodified. 597 * 598 * @throws UnsupportedOperationException always 599 * @deprecated Unsupported operation. 600 */ 601 @Deprecated 602 @Override 603 @DoNotCall("Always throws UnsupportedOperationException") 604 public final V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { 605 throw new UnsupportedOperationException(); 606 } 607 608 /** 609 * Guaranteed to throw an exception and leave the map unmodified. 610 * 611 * @throws UnsupportedOperationException always 612 * @deprecated Unsupported operation. 613 */ 614 @Deprecated 615 @Override 616 @DoNotCall("Always throws UnsupportedOperationException") 617 public final V merge( 618 K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) { 619 throw new UnsupportedOperationException(); 620 } 621 622 /** 623 * Guaranteed to throw an exception and leave the map unmodified. 624 * 625 * @throws UnsupportedOperationException always 626 * @deprecated Unsupported operation. 627 */ 628 @Deprecated 629 @Override 630 @DoNotCall("Always throws UnsupportedOperationException") 631 public final void putAll(Map<? extends K, ? extends V> map) { 632 throw new UnsupportedOperationException(); 633 } 634 635 /** 636 * Guaranteed to throw an exception and leave the map unmodified. 637 * 638 * @throws UnsupportedOperationException always 639 * @deprecated Unsupported operation. 640 */ 641 @Deprecated 642 @Override 643 @DoNotCall("Always throws UnsupportedOperationException") 644 public final void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { 645 throw new UnsupportedOperationException(); 646 } 647 648 /** 649 * Guaranteed to throw an exception and leave the map unmodified. 650 * 651 * @throws UnsupportedOperationException always 652 * @deprecated Unsupported operation. 653 */ 654 @Deprecated 655 @Override 656 @DoNotCall("Always throws UnsupportedOperationException") 657 public final V remove(Object o) { 658 throw new UnsupportedOperationException(); 659 } 660 661 /** 662 * Guaranteed to throw an exception and leave the map unmodified. 663 * 664 * @throws UnsupportedOperationException always 665 * @deprecated Unsupported operation. 666 */ 667 @Deprecated 668 @Override 669 @DoNotCall("Always throws UnsupportedOperationException") 670 public final boolean remove(Object key, Object value) { 671 throw new UnsupportedOperationException(); 672 } 673 674 /** 675 * Guaranteed to throw an exception and leave the map unmodified. 676 * 677 * @throws UnsupportedOperationException always 678 * @deprecated Unsupported operation. 679 */ 680 @Deprecated 681 @Override 682 @DoNotCall("Always throws UnsupportedOperationException") 683 public final void clear() { 684 throw new UnsupportedOperationException(); 685 } 686 687 @Override 688 public boolean isEmpty() { 689 return size() == 0; 690 } 691 692 @Override 693 public boolean containsKey(@Nullable Object key) { 694 return get(key) != null; 695 } 696 697 @Override 698 public boolean containsValue(@Nullable Object value) { 699 return values().contains(value); 700 } 701 702 // Overriding to mark it Nullable 703 @Override 704 public abstract V get(@Nullable Object key); 705 706 /** 707 * @since 21.0 (but only since 23.5 in the Android <a 708 * href="https://github.com/google/guava#guava-google-core-libraries-for-java">flavor</a>). 709 * Note, however, that Java 8 users can call this method with any version and flavor of Guava. 710 */ 711 @Override 712 public final V getOrDefault(@Nullable Object key, @Nullable V defaultValue) { 713 V result = get(key); 714 return (result != null) ? result : defaultValue; 715 } 716 717 @LazyInit @RetainedWith private transient ImmutableSet<Entry<K, V>> entrySet; 718 719 /** 720 * Returns an immutable set of the mappings in this map. The iteration order is specified by the 721 * method used to create this map. Typically, this is insertion order. 722 */ 723 @Override 724 public ImmutableSet<Entry<K, V>> entrySet() { 725 ImmutableSet<Entry<K, V>> result = entrySet; 726 return (result == null) ? entrySet = createEntrySet() : result; 727 } 728 729 abstract ImmutableSet<Entry<K, V>> createEntrySet(); 730 731 @LazyInit @RetainedWith private transient ImmutableSet<K> keySet; 732 733 /** 734 * Returns an immutable set of the keys in this map, in the same order that they appear in {@link 735 * #entrySet}. 736 */ 737 @Override 738 public ImmutableSet<K> keySet() { 739 ImmutableSet<K> result = keySet; 740 return (result == null) ? keySet = createKeySet() : result; 741 } 742 743 /* 744 * This could have a good default implementation of return new ImmutableKeySet<K, V>(this), 745 * but ProGuard can't figure out how to eliminate that default when RegularImmutableMap 746 * overrides it. 747 */ 748 abstract ImmutableSet<K> createKeySet(); 749 750 UnmodifiableIterator<K> keyIterator() { 751 final UnmodifiableIterator<Entry<K, V>> entryIterator = entrySet().iterator(); 752 return new UnmodifiableIterator<K>() { 753 @Override 754 public boolean hasNext() { 755 return entryIterator.hasNext(); 756 } 757 758 @Override 759 public K next() { 760 return entryIterator.next().getKey(); 761 } 762 }; 763 } 764 765 Spliterator<K> keySpliterator() { 766 return CollectSpliterators.map(entrySet().spliterator(), Entry::getKey); 767 } 768 769 @LazyInit @RetainedWith private transient ImmutableCollection<V> values; 770 771 /** 772 * Returns an immutable collection of the values in this map, in the same order that they appear 773 * in {@link #entrySet}. 774 */ 775 @Override 776 public ImmutableCollection<V> values() { 777 ImmutableCollection<V> result = values; 778 return (result == null) ? values = createValues() : result; 779 } 780 781 /* 782 * This could have a good default implementation of {@code return new 783 * ImmutableMapValues<K, V>(this)}, but ProGuard can't figure out how to eliminate that default 784 * when RegularImmutableMap overrides it. 785 */ 786 abstract ImmutableCollection<V> createValues(); 787 788 // cached so that this.multimapView().inverse() only computes inverse once 789 @LazyInit private transient ImmutableSetMultimap<K, V> multimapView; 790 791 /** 792 * Returns a multimap view of the map. 793 * 794 * @since 14.0 795 */ 796 public ImmutableSetMultimap<K, V> asMultimap() { 797 if (isEmpty()) { 798 return ImmutableSetMultimap.of(); 799 } 800 ImmutableSetMultimap<K, V> result = multimapView; 801 return (result == null) 802 ? (multimapView = 803 new ImmutableSetMultimap<>(new MapViewOfValuesAsSingletonSets(), size(), null)) 804 : result; 805 } 806 807 @WeakOuter 808 private final class MapViewOfValuesAsSingletonSets 809 extends IteratorBasedImmutableMap<K, ImmutableSet<V>> { 810 811 @Override 812 public int size() { 813 return ImmutableMap.this.size(); 814 } 815 816 @Override 817 ImmutableSet<K> createKeySet() { 818 return ImmutableMap.this.keySet(); 819 } 820 821 @Override 822 public boolean containsKey(@Nullable Object key) { 823 return ImmutableMap.this.containsKey(key); 824 } 825 826 @Override 827 public ImmutableSet<V> get(@Nullable Object key) { 828 V outerValue = ImmutableMap.this.get(key); 829 return (outerValue == null) ? null : ImmutableSet.of(outerValue); 830 } 831 832 @Override 833 boolean isPartialView() { 834 return ImmutableMap.this.isPartialView(); 835 } 836 837 @Override 838 public int hashCode() { 839 // ImmutableSet.of(value).hashCode() == value.hashCode(), so the hashes are the same 840 return ImmutableMap.this.hashCode(); 841 } 842 843 @Override 844 boolean isHashCodeFast() { 845 return ImmutableMap.this.isHashCodeFast(); 846 } 847 848 @Override 849 UnmodifiableIterator<Entry<K, ImmutableSet<V>>> entryIterator() { 850 final Iterator<Entry<K, V>> backingIterator = ImmutableMap.this.entrySet().iterator(); 851 return new UnmodifiableIterator<Entry<K, ImmutableSet<V>>>() { 852 @Override 853 public boolean hasNext() { 854 return backingIterator.hasNext(); 855 } 856 857 @Override 858 public Entry<K, ImmutableSet<V>> next() { 859 final Entry<K, V> backingEntry = backingIterator.next(); 860 return new AbstractMapEntry<K, ImmutableSet<V>>() { 861 @Override 862 public K getKey() { 863 return backingEntry.getKey(); 864 } 865 866 @Override 867 public ImmutableSet<V> getValue() { 868 return ImmutableSet.of(backingEntry.getValue()); 869 } 870 }; 871 } 872 }; 873 } 874 } 875 876 @Override 877 public boolean equals(@Nullable Object object) { 878 return Maps.equalsImpl(this, object); 879 } 880 881 abstract boolean isPartialView(); 882 883 @Override 884 public int hashCode() { 885 return Sets.hashCodeImpl(entrySet()); 886 } 887 888 boolean isHashCodeFast() { 889 return false; 890 } 891 892 @Override 893 public String toString() { 894 return Maps.toStringImpl(this); 895 } 896 897 /** 898 * Serialized type for all ImmutableMap instances. It captures the logical contents and they are 899 * reconstructed using public factory methods. This ensures that the implementation types remain 900 * as implementation details. 901 */ 902 static class SerializedForm<K, V> implements Serializable { 903 // This object retains references to collections returned by keySet() and value(). This saves 904 // bytes when the both the map and its keySet or value collection are written to the same 905 // instance of ObjectOutputStream. 906 907 // TODO(b/160980469): remove support for the old serialization format after some time 908 private static final boolean USE_LEGACY_SERIALIZATION = true; 909 910 private final Object keys; 911 private final Object values; 912 913 SerializedForm(ImmutableMap<K, V> map) { 914 if (USE_LEGACY_SERIALIZATION) { 915 Object[] keys = new Object[map.size()]; 916 Object[] values = new Object[map.size()]; 917 int i = 0; 918 for (Entry<?, ?> entry : map.entrySet()) { 919 keys[i] = entry.getKey(); 920 values[i] = entry.getValue(); 921 i++; 922 } 923 this.keys = keys; 924 this.values = values; 925 return; 926 } 927 this.keys = map.keySet(); 928 this.values = map.values(); 929 } 930 931 @SuppressWarnings("unchecked") 932 final Object readResolve() { 933 if (!(this.keys instanceof ImmutableSet)) { 934 return legacyReadResolve(); 935 } 936 937 ImmutableSet<K> keySet = (ImmutableSet<K>) this.keys; 938 ImmutableCollection<V> values = (ImmutableCollection<V>) this.values; 939 940 Builder<K, V> builder = makeBuilder(keySet.size()); 941 942 UnmodifiableIterator<K> keyIter = keySet.iterator(); 943 UnmodifiableIterator<V> valueIter = values.iterator(); 944 945 while (keyIter.hasNext()) { 946 builder.put(keyIter.next(), valueIter.next()); 947 } 948 949 return builder.build(); 950 } 951 952 @SuppressWarnings("unchecked") 953 final Object legacyReadResolve() { 954 K[] keys = (K[]) this.keys; 955 V[] values = (V[]) this.values; 956 957 Builder<K, V> builder = makeBuilder(keys.length); 958 959 for (int i = 0; i < keys.length; i++) { 960 builder.put(keys[i], values[i]); 961 } 962 return builder.build(); 963 } 964 965 /** 966 * Returns a builder that builds the unserialized type. Subclasses should override this method. 967 */ 968 Builder<K, V> makeBuilder(int size) { 969 return new Builder<>(size); 970 } 971 972 private static final long serialVersionUID = 0; 973 } 974 975 /** 976 * Returns a serializable form of this object. Non-public subclasses should not override this 977 * method. Publicly-accessible subclasses must override this method and should return a subclass 978 * of SerializedForm whose readResolve() method returns objects of the subclass type. 979 */ 980 Object writeReplace() { 981 return new SerializedForm<>(this); 982 } 983}