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