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