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