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