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