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;
023
024import com.google.common.annotations.Beta;
025import com.google.common.annotations.GwtCompatible;
026import com.google.errorprone.annotations.CanIgnoreReturnValue;
027import com.google.errorprone.annotations.concurrent.LazyInit;
028import com.google.j2objc.annotations.WeakOuter;
029import java.io.Serializable;
030import java.util.AbstractMap;
031import java.util.Arrays;
032import java.util.Collection;
033import java.util.Collections;
034import java.util.Comparator;
035import java.util.EnumMap;
036import java.util.Iterator;
037import java.util.LinkedHashMap;
038import java.util.Map;
039import java.util.Map.Entry;
040import java.util.SortedMap;
041import java.util.Spliterator;
042import java.util.Spliterators;
043import java.util.function.BiFunction;
044import java.util.function.BinaryOperator;
045import java.util.function.Function;
046import java.util.stream.Collector;
047import java.util.stream.Collectors;
048import javax.annotation.Nullable;
049
050/**
051 * A {@link Map} whose contents will never change, with many other important properties detailed at
052 * {@link ImmutableCollection}.
053 *
054 * <p>See the Guava User Guide article on <a href=
055 * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
056 * immutable collections</a>.
057 *
058 * @author Jesse Wilson
059 * @author Kevin Bourrillion
060 * @since 2.0
061 */
062@GwtCompatible(serializable = true, emulated = true)
063@SuppressWarnings("serial") // we're overriding default serialization
064public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
065
066  /**
067   * Returns a {@link Collector} that accumulates elements into an {@code ImmutableMap} whose keys
068   * and values are the result of applying the provided mapping functions to the input elements.
069   * Entries appear in the result {@code ImmutableMap} in encounter order.
070   *
071   * <p>If the mapped keys contain duplicates (according to {@link Object#equals(Object)}, an
072   * {@code IllegalArgumentException} is thrown when the collection operation is performed.
073   * (This differs from the {@code Collector} returned by
074   * {@link Collectors#toMap(Function, Function)}, which throws an {@code IllegalStateException}.)
075   *
076   * @since 21.0
077   */
078  @Beta
079  public static <T, K, V> Collector<T, ?, ImmutableMap<K, V>> toImmutableMap(
080      Function<? super T, ? extends K> keyFunction,
081      Function<? super T, ? extends V> valueFunction) {
082    return CollectCollectors.toImmutableMap(keyFunction, valueFunction);
083  }
084
085  /**
086   * Returns a {@link Collector} that accumulates elements into an {@code ImmutableMap} whose keys
087   * and values are the result of applying the provided mapping functions to the input elements.
088   *
089   * <p>If the mapped keys contain duplicates (according to {@link Object#equals(Object)}), the
090   * values are merged using the specified merging function. Entries will appear in the encounter
091   * order of the first occurrence of the key.
092   *
093   * @since 21.0
094   */
095  @Beta
096  public static <T, K, V> Collector<T, ?, ImmutableMap<K, V>> toImmutableMap(
097      Function<? super T, ? extends K> keyFunction,
098      Function<? super T, ? extends V> valueFunction,
099      BinaryOperator<V> mergeFunction) {
100    checkNotNull(keyFunction);
101    checkNotNull(valueFunction);
102    checkNotNull(mergeFunction);
103    return Collectors.collectingAndThen(
104        Collectors.toMap(keyFunction, valueFunction, mergeFunction, LinkedHashMap::new),
105        ImmutableMap::copyOf);
106  }
107
108  /**
109   * Returns the empty map. This map behaves and performs comparably to
110   * {@link Collections#emptyMap}, and is preferable mainly for consistency
111   * and maintainability of your code.
112   */
113  @SuppressWarnings("unchecked")
114  public static <K, V> ImmutableMap<K, V> of() {
115    return (ImmutableMap<K, V>) RegularImmutableMap.EMPTY;
116  }
117
118  /**
119   * Returns an immutable map containing a single entry. This map behaves and
120   * performs comparably to {@link Collections#singletonMap} but will not accept
121   * a null key or value. It is preferable mainly for consistency and
122   * maintainability of your code.
123   */
124  public static <K, V> ImmutableMap<K, V> of(K k1, V v1) {
125    return ImmutableBiMap.of(k1, v1);
126  }
127
128  /**
129   * Returns an immutable map containing the given entries, in order.
130   *
131   * @throws IllegalArgumentException if duplicate keys are provided
132   */
133  public static <K, V> ImmutableMap<K, V> of(K k1, V v1, K k2, V v2) {
134    return RegularImmutableMap.fromEntries(entryOf(k1, v1), entryOf(k2, v2));
135  }
136
137  /**
138   * Returns an immutable map containing the given entries, in order.
139   *
140   * @throws IllegalArgumentException if duplicate keys are provided
141   */
142  public static <K, V> ImmutableMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
143    return RegularImmutableMap.fromEntries(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3));
144  }
145
146  /**
147   * Returns an immutable map containing the given entries, in order.
148   *
149   * @throws IllegalArgumentException if duplicate keys are provided
150   */
151  public static <K, V> ImmutableMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
152    return RegularImmutableMap.fromEntries(
153        entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4));
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(
162      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
163    return RegularImmutableMap.fromEntries(
164        entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5));
165  }
166
167  // looking for of() with > 5 entries? Use the builder instead.
168
169  /**
170   * Verifies that {@code key} and {@code value} are non-null, and returns a new immutable entry
171   * with those values.
172   *
173   * <p>A call to {@link Entry#setValue} on the returned entry will always throw {@link
174   * UnsupportedOperationException}.
175   */
176  static <K, V> Entry<K, V> entryOf(K key, V value) {
177    checkEntryNotNull(key, value);
178    return new AbstractMap.SimpleImmutableEntry<>(key, value);
179  }
180
181  /**
182   * Returns a new builder. The generated builder is equivalent to the builder
183   * created by the {@link Builder} constructor.
184   */
185  public static <K, V> Builder<K, V> builder() {
186    return new Builder<>();
187  }
188
189  /**
190   * Returns a new builder, expecting the specified number of entries to be added.
191   *
192   * <p>If {@code expectedSize} is exactly the number of entries added to the builder before {@link
193   * Builder#build} is called, the builder is likely to perform better than an unsized {@link
194   * #builder()} would have.
195   *
196   * <p>It is not specified if any performance benefits apply if {@code expectedSize} is close to,
197   * but not exactly, the number of entries added to the builder.
198   * 
199   * @since 23.1
200   */
201  @Beta
202  public static <K, V> Builder<K, V> builderWithExpectedSize(int expectedSize) {
203    checkNonnegative(expectedSize, "expectedSize");
204    return new Builder<>(expectedSize);
205  }
206
207  static void checkNoConflict(
208      boolean safe, String conflictDescription, Entry<?, ?> entry1, Entry<?, ?> entry2) {
209    if (!safe) {
210      throw new IllegalArgumentException(
211          "Multiple entries with same " + conflictDescription + ": " + entry1 + " and " + entry2);
212    }
213  }
214
215  /**
216   * A builder for creating immutable map instances, especially {@code public static final} maps
217   * ("constant maps"). Example: <pre>   {@code
218   *
219   *   static final ImmutableMap<String, Integer> WORD_TO_INT =
220   *       new ImmutableMap.Builder<String, Integer>()
221   *           .put("one", 1)
222   *           .put("two", 2)
223   *           .put("three", 3)
224   *           .build();}</pre>
225   *
226   * <p>For <i>small</i> immutable maps, the {@code ImmutableMap.of()} methods are even more
227   * convenient.
228   *
229   * <p>By default, a {@code Builder} will generate maps that iterate over entries in the order
230   * they were inserted into the builder, equivalently to {@code LinkedHashMap}.  For example, in
231   * the above example, {@code WORD_TO_INT.entrySet()} is guaranteed to iterate over the entries in
232   * the order {@code "one"=1, "two"=2, "three"=3}, and {@code keySet()} and {@code values()}
233   * respect the same order.   If you want a different order, consider using 
234   * {@link ImmutableSortedMap} to sort by keys, or call {@link #orderEntriesByValue(Comparator)}, 
235   * which changes this builder to sort entries by value.
236   *
237   * <p>Builder instances can be reused - it is safe to call {@link #build}
238   * multiple times to build multiple maps in series. Each map is a superset of
239   * the maps created before it.
240   *
241   * @since 2.0
242   */
243  public static class Builder<K, V> {
244    Comparator<? super V> valueComparator;
245    Entry<K, V>[] entries;
246    int size;
247    boolean entriesUsed;
248
249    /**
250     * Creates a new builder. The returned builder is equivalent to the builder
251     * generated by {@link ImmutableMap#builder}.
252     */
253    public Builder() {
254      this(ImmutableCollection.Builder.DEFAULT_INITIAL_CAPACITY);
255    }
256
257    @SuppressWarnings("unchecked")
258    Builder(int initialCapacity) {
259      this.entries = new Entry[initialCapacity];
260      this.size = 0;
261      this.entriesUsed = false;
262    }
263
264    private void ensureCapacity(int minCapacity) {
265      if (minCapacity > entries.length) {
266        entries =
267            Arrays.copyOf(
268                entries, ImmutableCollection.Builder.expandedCapacity(entries.length, minCapacity));
269        entriesUsed = false;
270      }
271    }
272
273    /**
274     * Associates {@code key} with {@code value} in the built map. Duplicate
275     * keys are not allowed, and will cause {@link #build} to fail.
276     */
277    @CanIgnoreReturnValue
278    public Builder<K, V> put(K key, V value) {
279      ensureCapacity(size + 1);
280      Entry<K, V> entry = entryOf(key, value);
281      // don't inline this: we want to fail atomically if key or value is null
282      entries[size++] = entry;
283      return this;
284    }
285
286    /**
287     * Adds the given {@code entry} to the map, making it immutable if
288     * necessary. Duplicate keys are not allowed, and will cause {@link #build}
289     * to fail.
290     *
291     * @since 11.0
292     */
293    @CanIgnoreReturnValue
294    public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
295      return put(entry.getKey(), entry.getValue());
296    }
297
298    /**
299     * Associates all of the given map's keys and values in the built map.
300     * Duplicate keys are not allowed, and will cause {@link #build} to fail.
301     *
302     * @throws NullPointerException if any key or value in {@code map} is null
303     */
304    @CanIgnoreReturnValue
305    public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
306      return putAll(map.entrySet());
307    }
308
309    /**
310     * Adds all of the given entries to the built map.  Duplicate keys are not
311     * allowed, and will cause {@link #build} to fail.
312     *
313     * @throws NullPointerException if any key, value, or entry is null
314     * @since 19.0
315     */
316    @CanIgnoreReturnValue
317    @Beta
318    public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
319      if (entries instanceof Collection) {
320        ensureCapacity(size + ((Collection<?>) entries).size());
321      }
322      for (Entry<? extends K, ? extends V> entry : entries) {
323        put(entry);
324      }
325      return this;
326    }
327
328    /**
329     * Configures this {@code Builder} to order entries by value according to the specified
330     * comparator.
331     *
332     * <p>The sort order is stable, that is, if two entries have values that compare
333     * as equivalent, the entry that was inserted first will be first in the built map's
334     * iteration order.
335     *
336     * @throws IllegalStateException if this method was already called
337     * @since 19.0
338     */
339    @CanIgnoreReturnValue
340    @Beta
341    public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) {
342      checkState(this.valueComparator == null, "valueComparator was already set");
343      this.valueComparator = checkNotNull(valueComparator, "valueComparator");
344      return this;
345    }
346
347    @CanIgnoreReturnValue
348    Builder<K, V> combine(Builder<K, V> other) {
349      checkNotNull(other);
350      ensureCapacity(this.size + other.size);
351      System.arraycopy(other.entries, 0, this.entries, this.size, other.size);
352      this.size += other.size;
353      return this;
354    }
355
356    /*
357     * TODO(kevinb): Should build() and the ImmutableBiMap & ImmutableSortedMap
358     * versions throw an IllegalStateException instead?
359     */
360
361    /**
362     * Returns a newly-created immutable map.  The iteration order of the returned map is
363     * the order in which entries were inserted into the builder, unless
364     * {@link #orderEntriesByValue} was called, in which case entries are sorted by value.
365     *
366     * @throws IllegalArgumentException if duplicate keys were added
367     */
368    public ImmutableMap<K, V> build() {
369      /*
370       * If entries is full, then this implementation may end up using the entries array
371       * directly and writing over the entry objects with non-terminal entries, but this is
372       * safe; if this Builder is used further, it will grow the entries array (so it can't
373       * affect the original array), and future build() calls will always copy any entry
374       * objects that cannot be safely reused.
375       */
376      if (valueComparator != null) {
377        if (entriesUsed) {
378          entries = Arrays.copyOf(entries, size);
379        }
380        Arrays.sort(
381            entries,
382            0,
383            size,
384            Ordering.from(valueComparator).onResultOf(Maps.<V>valueFunction()));
385      }
386      entriesUsed = size == entries.length;
387      switch (size) {
388        case 0:
389          return of();
390        case 1:
391          return of(entries[0].getKey(), entries[0].getValue());
392        default:
393          return RegularImmutableMap.fromEntryArray(size, entries);
394      }
395    }
396  }
397
398  /**
399   * Returns an immutable map containing the same entries as {@code map}. The returned map iterates
400   * over entries in the same order as the {@code entrySet} of the original map.  If {@code map}
401   * somehow contains entries with duplicate keys (for example, if it is a {@code SortedMap}
402   * whose comparator is not <i>consistent with equals</i>), the results of this method are
403   * undefined.
404   *
405   * <p>Despite the method name, this method attempts to avoid actually copying
406   * the data when it is safe to do so. The exact circumstances under which a
407   * copy will or will not be performed are undocumented and subject to change.
408   *
409   * @throws NullPointerException if any key or value in {@code map} is null
410   */
411  public static <K, V> ImmutableMap<K, V> copyOf(Map<? extends K, ? extends V> map) {
412    if ((map instanceof ImmutableMap) && !(map instanceof SortedMap)) {
413      @SuppressWarnings("unchecked") // safe since map is not writable
414      ImmutableMap<K, V> kvMap = (ImmutableMap<K, V>) map;
415      if (!kvMap.isPartialView()) {
416        return kvMap;
417      }
418    } else if (map instanceof EnumMap) {
419      @SuppressWarnings("unchecked") // safe since map is not writable
420      ImmutableMap<K, V> kvMap = (ImmutableMap<K, V>) copyOfEnumMap((EnumMap<?, ?>) map);
421      return kvMap;
422    }
423    return copyOf(map.entrySet());
424  }
425
426  /**
427   * Returns an immutable map containing the specified entries.  The returned
428   * map iterates over entries in the same order as the original iterable.
429   *
430   * @throws NullPointerException if any key, value, or entry is null
431   * @throws IllegalArgumentException if two entries have the same key
432   * @since 19.0
433   */
434  @Beta
435  public static <K, V> ImmutableMap<K, V> copyOf(
436      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
437    @SuppressWarnings("unchecked") // we'll only be using getKey and getValue, which are covariant
438    Entry<K, V>[] entryArray = (Entry<K, V>[]) Iterables.toArray(entries, EMPTY_ENTRY_ARRAY);
439    switch (entryArray.length) {
440      case 0:
441        return of();
442      case 1:
443        Entry<K, V> onlyEntry = entryArray[0];
444        return of(onlyEntry.getKey(), onlyEntry.getValue());
445      default:
446        /*
447         * The current implementation will end up using entryArray directly, though it will write
448         * over the (arbitrary, potentially mutable) Entry objects actually stored in entryArray.
449         */
450        return RegularImmutableMap.fromEntries(entryArray);
451    }
452  }
453
454  private static <K extends Enum<K>, V> ImmutableMap<K, V> copyOfEnumMap(
455      EnumMap<K, ? extends V> original) {
456    EnumMap<K, V> copy = new EnumMap<>(original);
457    for (Entry<?, ?> entry : copy.entrySet()) {
458      checkEntryNotNull(entry.getKey(), entry.getValue());
459    }
460    return ImmutableEnumMap.asImmutable(copy);
461  }
462
463  static final Entry<?, ?>[] EMPTY_ENTRY_ARRAY = new Entry<?, ?>[0];
464
465  abstract static class IteratorBasedImmutableMap<K, V> extends ImmutableMap<K, V> {
466    abstract UnmodifiableIterator<Entry<K, V>> entryIterator();
467
468    Spliterator<Entry<K, V>> entrySpliterator() {
469      return Spliterators.spliterator(
470          entryIterator(),
471          size(),
472          Spliterator.DISTINCT | Spliterator.NONNULL | Spliterator.IMMUTABLE | Spliterator.ORDERED);
473    }
474
475    @Override
476    ImmutableSet<K> createKeySet() {
477      return new ImmutableMapKeySet<>(this);
478    }
479
480    @Override
481    ImmutableSet<Entry<K, V>> createEntrySet() {
482      @WeakOuter
483      class EntrySetImpl extends ImmutableMapEntrySet<K, V> {
484        @Override
485        ImmutableMap<K, V> map() {
486          return IteratorBasedImmutableMap.this;
487        }
488
489        @Override
490        public UnmodifiableIterator<Entry<K, V>> iterator() {
491          return entryIterator();
492        }
493      }
494      return new EntrySetImpl();
495    }
496
497    @Override
498    ImmutableCollection<V> createValues() {
499      return new ImmutableMapValues<>(this);
500    }
501  }
502
503  ImmutableMap() {}
504
505  /**
506   * Guaranteed to throw an exception and leave the map unmodified.
507   *
508   * @throws UnsupportedOperationException always
509   * @deprecated Unsupported operation.
510   */
511  @CanIgnoreReturnValue
512  @Deprecated
513  @Override
514  public final V put(K k, V v) {
515    throw new UnsupportedOperationException();
516  }
517
518  /**
519   * Guaranteed to throw an exception and leave the map unmodified.
520   *
521   * @throws UnsupportedOperationException always
522   * @deprecated Unsupported operation.
523   */
524  @CanIgnoreReturnValue
525  @Deprecated
526  @Override
527  public final V putIfAbsent(K key, V value) {
528    throw new UnsupportedOperationException();
529  }
530
531  /**
532   * Guaranteed to throw an exception and leave the map unmodified.
533   *
534   * @throws UnsupportedOperationException always
535   * @deprecated Unsupported operation.
536   */
537  @Deprecated
538  @Override
539  public final boolean replace(K key, V oldValue, V newValue) {
540    throw new UnsupportedOperationException();
541  }
542
543  /**
544   * Guaranteed to throw an exception and leave the map unmodified.
545   *
546   * @throws UnsupportedOperationException always
547   * @deprecated Unsupported operation.
548   */
549  @Deprecated
550  @Override
551  public final V replace(K key, V value) {
552    throw new UnsupportedOperationException();
553  }
554
555  /**
556   * Guaranteed to throw an exception and leave the map unmodified.
557   *
558   * @throws UnsupportedOperationException always
559   * @deprecated Unsupported operation.
560   */
561  @Deprecated
562  @Override
563  public final V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
564    throw new UnsupportedOperationException();
565  }
566
567  /**
568   * Guaranteed to throw an exception and leave the map unmodified.
569   *
570   * @throws UnsupportedOperationException always
571   * @deprecated Unsupported operation.
572   */
573  @Deprecated
574  @Override
575  public final V computeIfPresent(
576      K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
577    throw new UnsupportedOperationException();
578  }
579
580  /**
581   * Guaranteed to throw an exception and leave the map unmodified.
582   *
583   * @throws UnsupportedOperationException always
584   * @deprecated Unsupported operation.
585   */
586  @Deprecated
587  @Override
588  public final V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
589    throw new UnsupportedOperationException();
590  }
591
592  /**
593   * Guaranteed to throw an exception and leave the map unmodified.
594   *
595   * @throws UnsupportedOperationException always
596   * @deprecated Unsupported operation.
597   */
598  @Deprecated
599  @Override
600  public final V merge(
601      K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
602    throw new UnsupportedOperationException();
603  }
604
605  /**
606   * Guaranteed to throw an exception and leave the map unmodified.
607   *
608   * @throws UnsupportedOperationException always
609   * @deprecated Unsupported operation.
610   */
611  @Deprecated
612  @Override
613  public final void putAll(Map<? extends K, ? extends V> map) {
614    throw new UnsupportedOperationException();
615  }
616
617  /**
618   * Guaranteed to throw an exception and leave the map unmodified.
619   *
620   * @throws UnsupportedOperationException always
621   * @deprecated Unsupported operation.
622   */
623  @Deprecated
624  @Override
625  public final void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
626    throw new UnsupportedOperationException();
627  }
628
629  /**
630   * Guaranteed to throw an exception and leave the map unmodified.
631   *
632   * @throws UnsupportedOperationException always
633   * @deprecated Unsupported operation.
634   */
635  @Deprecated
636  @Override
637  public final V remove(Object o) {
638    throw new UnsupportedOperationException();
639  }
640
641  /**
642   * Guaranteed to throw an exception and leave the map unmodified.
643   *
644   * @throws UnsupportedOperationException always
645   * @deprecated Unsupported operation.
646   */
647  @Deprecated
648  @Override
649  public final boolean remove(Object key, Object value) {
650    throw new UnsupportedOperationException();
651  }
652
653  /**
654   * Guaranteed to throw an exception and leave the map unmodified.
655   *
656   * @throws UnsupportedOperationException always
657   * @deprecated Unsupported operation.
658   */
659  @Deprecated
660  @Override
661  public final void clear() {
662    throw new UnsupportedOperationException();
663  }
664
665  @Override
666  public boolean isEmpty() {
667    return size() == 0;
668  }
669
670  @Override
671  public boolean containsKey(@Nullable Object key) {
672    return get(key) != null;
673  }
674
675  @Override
676  public boolean containsValue(@Nullable Object value) {
677    return values().contains(value);
678  }
679
680  // Overriding to mark it Nullable
681  @Override
682  public abstract V get(@Nullable Object key);
683
684  /**
685   * @since 21.0 (but only since 23.5 in the Android <a
686   *     href="https://github.com/google/guava#guava-google-core-libraries-for-java">flavor</a>).
687   *     Note, however, that Java 8 users can call this method with any version and flavor of Guava.
688   */
689  @Override
690  public final V getOrDefault(@Nullable Object key, @Nullable V defaultValue) {
691    V result = get(key);
692    return (result != null) ? result : defaultValue;
693  }
694
695  @LazyInit
696  private transient ImmutableSet<Entry<K, V>> entrySet;
697
698  /**
699   * Returns an immutable set of the mappings in this map.  The iteration order is specified by
700   * the method used to create this map.  Typically, this is insertion order.
701   */
702  @Override
703  public ImmutableSet<Entry<K, V>> entrySet() {
704    ImmutableSet<Entry<K, V>> result = entrySet;
705    return (result == null) ? entrySet = createEntrySet() : result;
706  }
707
708  abstract ImmutableSet<Entry<K, V>> createEntrySet();
709
710  @LazyInit
711  private transient ImmutableSet<K> keySet;
712
713  /**
714   * Returns an immutable set of the keys in this map, in the same order that they appear in
715   * {@link #entrySet}.
716   */
717  @Override
718  public ImmutableSet<K> keySet() {
719    ImmutableSet<K> result = keySet;
720    return (result == null) ? keySet = createKeySet() : result;
721  }
722
723  /*
724   * This could have a good default implementation of return new ImmutableKeySet<K, V>(this),
725   * but ProGuard can't figure out how to eliminate that default when RegularImmutableMap
726   * overrides it.
727   */
728  abstract ImmutableSet<K> createKeySet();
729
730  UnmodifiableIterator<K> keyIterator() {
731    final UnmodifiableIterator<Entry<K, V>> entryIterator = entrySet().iterator();
732    return new UnmodifiableIterator<K>() {
733      @Override
734      public boolean hasNext() {
735        return entryIterator.hasNext();
736      }
737
738      @Override
739      public K next() {
740        return entryIterator.next().getKey();
741      }
742    };
743  }
744
745  Spliterator<K> keySpliterator() {
746    return CollectSpliterators.map(entrySet().spliterator(), Entry::getKey);
747  }
748
749  @LazyInit
750  private transient ImmutableCollection<V> values;
751
752  /**
753   * Returns an immutable collection of the values in this map, in the same order that they appear
754   * in {@link #entrySet}.
755   */
756  @Override
757  public ImmutableCollection<V> values() {
758    ImmutableCollection<V> result = values;
759    return (result == null) ? values = createValues() : result;
760  }
761
762  /*
763   * This could have a good default implementation of {@code return new
764   * ImmutableMapValues<K, V>(this)}, but ProGuard can't figure out how to eliminate that default
765   * when RegularImmutableMap overrides it.
766   */
767  abstract ImmutableCollection<V> createValues();
768
769  // cached so that this.multimapView().inverse() only computes inverse once
770  @LazyInit
771  private transient ImmutableSetMultimap<K, V> multimapView;
772
773  /**
774   * Returns a multimap view of the map.
775   *
776   * @since 14.0
777   */
778  public ImmutableSetMultimap<K, V> asMultimap() {
779    if (isEmpty()) {
780      return ImmutableSetMultimap.of();
781    }
782    ImmutableSetMultimap<K, V> result = multimapView;
783    return (result == null)
784        ? (multimapView =
785            new ImmutableSetMultimap<>(new MapViewOfValuesAsSingletonSets(), size(), null))
786        : result;
787  }
788
789  @WeakOuter
790  private final class MapViewOfValuesAsSingletonSets
791      extends IteratorBasedImmutableMap<K, ImmutableSet<V>> {
792
793    @Override
794    public int size() {
795      return ImmutableMap.this.size();
796    }
797
798    @Override
799    ImmutableSet<K> createKeySet() {
800      return ImmutableMap.this.keySet();
801    }
802
803    @Override
804    public boolean containsKey(@Nullable Object key) {
805      return ImmutableMap.this.containsKey(key);
806    }
807
808    @Override
809    public ImmutableSet<V> get(@Nullable Object key) {
810      V outerValue = ImmutableMap.this.get(key);
811      return (outerValue == null) ? null : ImmutableSet.of(outerValue);
812    }
813
814    @Override
815    boolean isPartialView() {
816      return ImmutableMap.this.isPartialView();
817    }
818
819    @Override
820    public int hashCode() {
821      // ImmutableSet.of(value).hashCode() == value.hashCode(), so the hashes are the same
822      return ImmutableMap.this.hashCode();
823    }
824
825    @Override
826    boolean isHashCodeFast() {
827      return ImmutableMap.this.isHashCodeFast();
828    }
829
830    @Override
831    UnmodifiableIterator<Entry<K, ImmutableSet<V>>> entryIterator() {
832      final Iterator<Entry<K, V>> backingIterator = ImmutableMap.this.entrySet().iterator();
833      return new UnmodifiableIterator<Entry<K, ImmutableSet<V>>>() {
834        @Override
835        public boolean hasNext() {
836          return backingIterator.hasNext();
837        }
838
839        @Override
840        public Entry<K, ImmutableSet<V>> next() {
841          final Entry<K, V> backingEntry = backingIterator.next();
842          return new AbstractMapEntry<K, ImmutableSet<V>>() {
843            @Override
844            public K getKey() {
845              return backingEntry.getKey();
846            }
847
848            @Override
849            public ImmutableSet<V> getValue() {
850              return ImmutableSet.of(backingEntry.getValue());
851            }
852          };
853        }
854      };
855    }
856  }
857
858  @Override
859  public boolean equals(@Nullable Object object) {
860    return Maps.equalsImpl(this, object);
861  }
862
863  abstract boolean isPartialView();
864
865  @Override
866  public int hashCode() {
867    return Sets.hashCodeImpl(entrySet());
868  }
869
870  boolean isHashCodeFast() {
871    return false;
872  }
873
874  @Override
875  public String toString() {
876    return Maps.toStringImpl(this);
877  }
878
879  /**
880   * Serialized type for all ImmutableMap instances. It captures the logical
881   * contents and they are reconstructed using public factory methods. This
882   * ensures that the implementation types remain as implementation details.
883   */
884  static class SerializedForm implements Serializable {
885    private final Object[] keys;
886    private final Object[] values;
887
888    SerializedForm(ImmutableMap<?, ?> map) {
889      keys = new Object[map.size()];
890      values = new Object[map.size()];
891      int i = 0;
892      for (Entry<?, ?> entry : map.entrySet()) {
893        keys[i] = entry.getKey();
894        values[i] = entry.getValue();
895        i++;
896      }
897    }
898
899    Object readResolve() {
900      Builder<Object, Object> builder = new Builder<>(keys.length);
901      return createMap(builder);
902    }
903
904    Object createMap(Builder<Object, Object> builder) {
905      for (int i = 0; i < keys.length; i++) {
906        builder.put(keys[i], values[i]);
907      }
908      return builder.build();
909    }
910
911    private static final long serialVersionUID = 0;
912  }
913
914  Object writeReplace() {
915    return new SerializedForm(this);
916  }
917}