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