001/*
002 * Copyright (C) 2009 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.checkArgument;
020import static com.google.common.base.Preconditions.checkNotNull;
021import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
022import static com.google.common.collect.Maps.keyOrNull;
023
024import com.google.common.annotations.Beta;
025import com.google.common.annotations.GwtCompatible;
026import com.google.errorprone.annotations.CanIgnoreReturnValue;
027import com.google.errorprone.annotations.DoNotCall;
028import java.util.AbstractMap;
029import java.util.Arrays;
030import java.util.Comparator;
031import java.util.Map;
032import java.util.NavigableMap;
033import java.util.SortedMap;
034import java.util.Spliterator;
035import java.util.TreeMap;
036import java.util.function.BiConsumer;
037import java.util.function.BinaryOperator;
038import java.util.function.Consumer;
039import java.util.function.Function;
040import java.util.stream.Collector;
041import java.util.stream.Collectors;
042import org.checkerframework.checker.nullness.qual.Nullable;
043
044/**
045 * A {@link NavigableMap} whose contents will never change, with many other important properties
046 * detailed at {@link ImmutableCollection}.
047 *
048 * <p><b>Warning:</b> as with any sorted collection, you are strongly advised not to use a {@link
049 * Comparator} or {@link Comparable} type whose comparison behavior is <i>inconsistent with
050 * equals</i>. That is, {@code a.compareTo(b)} or {@code comparator.compare(a, b)} should equal zero
051 * <i>if and only if</i> {@code a.equals(b)}. If this advice is not followed, the resulting map will
052 * not correctly obey its specification.
053 *
054 * <p>See the Guava User Guide article on <a href=
055 * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained"> immutable collections</a>.
056 *
057 * @author Jared Levy
058 * @author Louis Wasserman
059 * @since 2.0 (implements {@code NavigableMap} since 12.0)
060 */
061@GwtCompatible(serializable = true, emulated = true)
062public final class ImmutableSortedMap<K, V> extends ImmutableSortedMapFauxverideShim<K, V>
063    implements NavigableMap<K, V> {
064  /**
065   * Returns a {@link Collector} that accumulates elements into an {@code ImmutableSortedMap} whose
066   * keys and values are the result of applying the provided mapping functions to the input
067   * elements. The generated map is sorted by the specified comparator.
068   *
069   * <p>If the mapped keys contain duplicates (according to the specified comparator), an {@code
070   * IllegalArgumentException} is thrown when the collection operation is performed. (This differs
071   * from the {@code Collector} returned by {@link Collectors#toMap(Function, Function)}, which
072   * throws an {@code IllegalStateException}.)
073   *
074   * @since 21.0
075   */
076  public static <T, K, V> Collector<T, ?, ImmutableSortedMap<K, V>> toImmutableSortedMap(
077      Comparator<? super K> comparator,
078      Function<? super T, ? extends K> keyFunction,
079      Function<? super T, ? extends V> valueFunction) {
080    return CollectCollectors.toImmutableSortedMap(comparator, keyFunction, valueFunction);
081  }
082
083  /**
084   * Returns a {@link Collector} that accumulates elements into an {@code ImmutableSortedMap} whose
085   * keys and values are the result of applying the provided mapping functions to the input
086   * elements.
087   *
088   * <p>If the mapped keys contain duplicates (according to the comparator), the the values are
089   * merged using the specified merging function. Entries will appear in the encounter order of the
090   * first occurrence of the key.
091   *
092   * @since 21.0
093   */
094  public static <T, K, V> Collector<T, ?, ImmutableSortedMap<K, V>> toImmutableSortedMap(
095      Comparator<? super K> comparator,
096      Function<? super T, ? extends K> keyFunction,
097      Function<? super T, ? extends V> valueFunction,
098      BinaryOperator<V> mergeFunction) {
099    return CollectCollectors.toImmutableSortedMap(
100        comparator, keyFunction, valueFunction, mergeFunction);
101  }
102
103  /*
104   * TODO(kevinb): Confirm that ImmutableSortedMap is faster to construct and
105   * uses less memory than TreeMap; then say so in the class Javadoc.
106   */
107  private static final Comparator<Comparable> NATURAL_ORDER = Ordering.natural();
108
109  private static final ImmutableSortedMap<Comparable, Object> NATURAL_EMPTY_MAP =
110      new ImmutableSortedMap<>(
111          ImmutableSortedSet.emptySet(Ordering.natural()), ImmutableList.<Object>of());
112
113  static <K, V> ImmutableSortedMap<K, V> emptyMap(Comparator<? super K> comparator) {
114    if (Ordering.natural().equals(comparator)) {
115      return of();
116    } else {
117      return new ImmutableSortedMap<>(
118          ImmutableSortedSet.emptySet(comparator), ImmutableList.<V>of());
119    }
120  }
121
122  /** Returns the empty sorted map. */
123  @SuppressWarnings("unchecked")
124  // unsafe, comparator() returns a comparator on the specified type
125  // TODO(kevinb): evaluate whether or not of().comparator() should return null
126  public static <K, V> ImmutableSortedMap<K, V> of() {
127    return (ImmutableSortedMap<K, V>) NATURAL_EMPTY_MAP;
128  }
129
130  /** Returns an immutable map containing a single entry. */
131  public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of(K k1, V v1) {
132    return of(Ordering.natural(), k1, v1);
133  }
134
135  /** Returns an immutable map containing a single entry. */
136  private static <K, V> ImmutableSortedMap<K, V> of(Comparator<? super K> comparator, K k1, V v1) {
137    return new ImmutableSortedMap<>(
138        new RegularImmutableSortedSet<K>(ImmutableList.of(k1), checkNotNull(comparator)),
139        ImmutableList.of(v1));
140  }
141
142  /**
143   * Returns an immutable sorted map containing the given entries, sorted by the natural ordering of
144   * their keys.
145   *
146   * @throws IllegalArgumentException if the two keys are equal according to their natural ordering
147   */
148  @SuppressWarnings("unchecked")
149  public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of(
150      K k1, V v1, K k2, V v2) {
151    return ofEntries(entryOf(k1, v1), entryOf(k2, v2));
152  }
153
154  /**
155   * Returns an immutable sorted map containing the given entries, sorted by the natural ordering of
156   * their keys.
157   *
158   * @throws IllegalArgumentException if any two keys are equal according to their natural ordering
159   */
160  @SuppressWarnings("unchecked")
161  public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of(
162      K k1, V v1, K k2, V v2, K k3, V v3) {
163    return ofEntries(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3));
164  }
165
166  /**
167   * Returns an immutable sorted map containing the given entries, sorted by the natural ordering of
168   * their keys.
169   *
170   * @throws IllegalArgumentException if any two keys are equal according to their natural ordering
171   */
172  @SuppressWarnings("unchecked")
173  public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of(
174      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
175    return ofEntries(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4));
176  }
177
178  /**
179   * Returns an immutable sorted map containing the given entries, sorted by the natural ordering of
180   * their keys.
181   *
182   * @throws IllegalArgumentException if any two keys are equal according to their natural ordering
183   */
184  @SuppressWarnings("unchecked")
185  public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of(
186      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
187    return ofEntries(
188        entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5));
189  }
190
191  private static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> ofEntries(
192      Entry<K, V>... entries) {
193    return fromEntries(Ordering.natural(), false, entries, entries.length);
194  }
195
196  /**
197   * Returns an immutable map containing the same entries as {@code map}, sorted by the natural
198   * ordering of the keys.
199   *
200   * <p>Despite the method name, this method attempts to avoid actually copying the data when it is
201   * safe to do so. The exact circumstances under which a copy will or will not be performed are
202   * undocumented and subject to change.
203   *
204   * <p>This method is not type-safe, as it may be called on a map with keys that are not mutually
205   * comparable.
206   *
207   * @throws ClassCastException if the keys in {@code map} are not mutually comparable
208   * @throws NullPointerException if any key or value in {@code map} is null
209   * @throws IllegalArgumentException if any two keys are equal according to their natural ordering
210   */
211  public static <K, V> ImmutableSortedMap<K, V> copyOf(Map<? extends K, ? extends V> map) {
212    // Hack around K not being a subtype of Comparable.
213    // Unsafe, see ImmutableSortedSetFauxverideShim.
214    @SuppressWarnings("unchecked")
215    Ordering<K> naturalOrder = (Ordering<K>) NATURAL_ORDER;
216    return copyOfInternal(map, naturalOrder);
217  }
218
219  /**
220   * Returns an immutable map containing the same entries as {@code map}, with keys sorted by the
221   * provided comparator.
222   *
223   * <p>Despite the method name, this method attempts to avoid actually copying the data when it is
224   * safe to do so. The exact circumstances under which a copy will or will not be performed are
225   * undocumented and subject to change.
226   *
227   * @throws NullPointerException if any key or value in {@code map} is null
228   * @throws IllegalArgumentException if any two keys are equal according to the comparator
229   */
230  public static <K, V> ImmutableSortedMap<K, V> copyOf(
231      Map<? extends K, ? extends V> map, Comparator<? super K> comparator) {
232    return copyOfInternal(map, checkNotNull(comparator));
233  }
234
235  /**
236   * Returns an immutable map containing the given entries, with keys sorted by their natural
237   * ordering.
238   *
239   * <p>This method is not type-safe, as it may be called on a map with keys that are not mutually
240   * comparable.
241   *
242   * @throws NullPointerException if any key or value in {@code map} is null
243   * @throws IllegalArgumentException if any two keys are equal according to the comparator
244   * @since 19.0
245   */
246  @Beta
247  public static <K, V> ImmutableSortedMap<K, V> copyOf(
248      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
249    // Hack around K not being a subtype of Comparable.
250    // Unsafe, see ImmutableSortedSetFauxverideShim.
251    @SuppressWarnings("unchecked")
252    Ordering<K> naturalOrder = (Ordering<K>) NATURAL_ORDER;
253    return copyOf(entries, naturalOrder);
254  }
255
256  /**
257   * Returns an immutable map containing the given entries, with keys sorted by the provided
258   * comparator.
259   *
260   * @throws NullPointerException if any key or value in {@code map} is null
261   * @throws IllegalArgumentException if any two keys are equal according to the comparator
262   * @since 19.0
263   */
264  @Beta
265  public static <K, V> ImmutableSortedMap<K, V> copyOf(
266      Iterable<? extends Entry<? extends K, ? extends V>> entries,
267      Comparator<? super K> comparator) {
268    return fromEntries(checkNotNull(comparator), false, entries);
269  }
270
271  /**
272   * Returns an immutable map containing the same entries as the provided sorted map, with the same
273   * ordering.
274   *
275   * <p>Despite the method name, this method attempts to avoid actually copying the data when it is
276   * safe to do so. The exact circumstances under which a copy will or will not be performed are
277   * undocumented and subject to change.
278   *
279   * @throws NullPointerException if any key or value in {@code map} is null
280   */
281  @SuppressWarnings("unchecked")
282  public static <K, V> ImmutableSortedMap<K, V> copyOfSorted(SortedMap<K, ? extends V> map) {
283    Comparator<? super K> comparator = map.comparator();
284    if (comparator == null) {
285      // If map has a null comparator, the keys should have a natural ordering,
286      // even though K doesn't explicitly implement Comparable.
287      comparator = (Comparator<? super K>) NATURAL_ORDER;
288    }
289    if (map instanceof ImmutableSortedMap) {
290      // TODO(kevinb): Prove that this cast is safe, even though
291      // Collections.unmodifiableSortedMap requires the same key type.
292      @SuppressWarnings("unchecked")
293      ImmutableSortedMap<K, V> kvMap = (ImmutableSortedMap<K, V>) map;
294      if (!kvMap.isPartialView()) {
295        return kvMap;
296      }
297    }
298    return fromEntries(comparator, true, map.entrySet());
299  }
300
301  private static <K, V> ImmutableSortedMap<K, V> copyOfInternal(
302      Map<? extends K, ? extends V> map, Comparator<? super K> comparator) {
303    boolean sameComparator = false;
304    if (map instanceof SortedMap) {
305      SortedMap<?, ?> sortedMap = (SortedMap<?, ?>) map;
306      Comparator<?> comparator2 = sortedMap.comparator();
307      sameComparator =
308          (comparator2 == null) ? comparator == NATURAL_ORDER : comparator.equals(comparator2);
309    }
310
311    if (sameComparator && (map instanceof ImmutableSortedMap)) {
312      // TODO(kevinb): Prove that this cast is safe, even though
313      // Collections.unmodifiableSortedMap requires the same key type.
314      @SuppressWarnings("unchecked")
315      ImmutableSortedMap<K, V> kvMap = (ImmutableSortedMap<K, V>) map;
316      if (!kvMap.isPartialView()) {
317        return kvMap;
318      }
319    }
320    return fromEntries(comparator, sameComparator, map.entrySet());
321  }
322
323  /**
324   * Accepts a collection of possibly-null entries. If {@code sameComparator}, then it is assumed
325   * that they do not need to be sorted or checked for dupes.
326   */
327  private static <K, V> ImmutableSortedMap<K, V> fromEntries(
328      Comparator<? super K> comparator,
329      boolean sameComparator,
330      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
331    // "adding" type params to an array of a raw type should be safe as
332    // long as no one can ever cast that same array instance back to a
333    // raw type.
334    @SuppressWarnings("unchecked")
335    Entry<K, V>[] entryArray = (Entry[]) Iterables.toArray(entries, EMPTY_ENTRY_ARRAY);
336    return fromEntries(comparator, sameComparator, entryArray, entryArray.length);
337  }
338
339  private static <K, V> ImmutableSortedMap<K, V> fromEntries(
340      final Comparator<? super K> comparator,
341      boolean sameComparator,
342      Entry<K, V>[] entryArray,
343      int size) {
344    switch (size) {
345      case 0:
346        return emptyMap(comparator);
347      case 1:
348        return ImmutableSortedMap.<K, V>of(
349            comparator, entryArray[0].getKey(), entryArray[0].getValue());
350      default:
351        Object[] keys = new Object[size];
352        Object[] values = new Object[size];
353        if (sameComparator) {
354          // Need to check for nulls, but don't need to sort or validate.
355          for (int i = 0; i < size; i++) {
356            Object key = entryArray[i].getKey();
357            Object value = entryArray[i].getValue();
358            checkEntryNotNull(key, value);
359            keys[i] = key;
360            values[i] = value;
361          }
362        } else {
363          // Need to sort and check for nulls and dupes.
364          // Inline the Comparator implementation rather than transforming with a Function
365          // to save code size.
366          Arrays.sort(
367              entryArray,
368              0,
369              size,
370              new Comparator<Entry<K, V>>() {
371                @Override
372                public int compare(Entry<K, V> e1, Entry<K, V> e2) {
373                  return comparator.compare(e1.getKey(), e2.getKey());
374                }
375              });
376          K prevKey = entryArray[0].getKey();
377          keys[0] = prevKey;
378          values[0] = entryArray[0].getValue();
379          checkEntryNotNull(keys[0], values[0]);
380          for (int i = 1; i < size; i++) {
381            K key = entryArray[i].getKey();
382            V value = entryArray[i].getValue();
383            checkEntryNotNull(key, value);
384            keys[i] = key;
385            values[i] = value;
386            checkNoConflict(
387                comparator.compare(prevKey, key) != 0, "key", entryArray[i - 1], entryArray[i]);
388            prevKey = key;
389          }
390        }
391        return new ImmutableSortedMap<>(
392            new RegularImmutableSortedSet<K>(new RegularImmutableList<K>(keys), comparator),
393            new RegularImmutableList<V>(values));
394    }
395  }
396
397  /**
398   * Returns a builder that creates immutable sorted maps whose keys are ordered by their natural
399   * ordering. The sorted maps use {@link Ordering#natural()} as the comparator.
400   */
401  public static <K extends Comparable<?>, V> Builder<K, V> naturalOrder() {
402    return new Builder<>(Ordering.natural());
403  }
404
405  /**
406   * Returns a builder that creates immutable sorted maps with an explicit comparator. If the
407   * comparator has a more general type than the map's keys, such as creating a {@code
408   * SortedMap<Integer, String>} with a {@code Comparator<Number>}, use the {@link Builder}
409   * constructor instead.
410   *
411   * @throws NullPointerException if {@code comparator} is null
412   */
413  public static <K, V> Builder<K, V> orderedBy(Comparator<K> comparator) {
414    return new Builder<>(comparator);
415  }
416
417  /**
418   * Returns a builder that creates immutable sorted maps whose keys are ordered by the reverse of
419   * their natural ordering.
420   */
421  public static <K extends Comparable<?>, V> Builder<K, V> reverseOrder() {
422    return new Builder<>(Ordering.natural().reverse());
423  }
424
425  /**
426   * A builder for creating immutable sorted map instances, especially {@code public static final}
427   * maps ("constant maps"). Example:
428   *
429   * <pre>{@code
430   * static final ImmutableSortedMap<Integer, String> INT_TO_WORD =
431   *     new ImmutableSortedMap.Builder<Integer, String>(Ordering.natural())
432   *         .put(1, "one")
433   *         .put(2, "two")
434   *         .put(3, "three")
435   *         .build();
436   * }</pre>
437   *
438   * <p>For <i>small</i> immutable sorted maps, the {@code ImmutableSortedMap.of()} methods are even
439   * more convenient.
440   *
441   * <p>Builder instances can be reused - it is safe to call {@link #build} multiple times to build
442   * multiple maps in series. Each map is a superset of the maps created before it.
443   *
444   * @since 2.0
445   */
446  public static class Builder<K, V> extends ImmutableMap.Builder<K, V> {
447    private final Comparator<? super K> comparator;
448
449    /**
450     * Creates a new builder. The returned builder is equivalent to the builder generated by {@link
451     * ImmutableSortedMap#orderedBy}.
452     */
453    @SuppressWarnings("unchecked")
454    public Builder(Comparator<? super K> comparator) {
455      this.comparator = checkNotNull(comparator);
456    }
457
458    /**
459     * Associates {@code key} with {@code value} in the built map. Duplicate keys, according to the
460     * comparator (which might be the keys' natural order), are not allowed, and will cause {@link
461     * #build} to fail.
462     */
463    @CanIgnoreReturnValue
464    @Override
465    public Builder<K, V> put(K key, V value) {
466      super.put(key, value);
467      return this;
468    }
469
470    /**
471     * Adds the given {@code entry} to the map, making it immutable if necessary. Duplicate keys,
472     * according to the comparator (which might be the keys' natural order), are not allowed, and
473     * will cause {@link #build} to fail.
474     *
475     * @since 11.0
476     */
477    @CanIgnoreReturnValue
478    @Override
479    public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
480      super.put(entry);
481      return this;
482    }
483
484    /**
485     * Associates all of the given map's keys and values in the built map. Duplicate keys, according
486     * to the comparator (which might be the keys' natural order), are not allowed, and will cause
487     * {@link #build} to fail.
488     *
489     * @throws NullPointerException if any key or value in {@code map} is null
490     */
491    @CanIgnoreReturnValue
492    @Override
493    public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
494      super.putAll(map);
495      return this;
496    }
497
498    /**
499     * Adds all the given entries to the built map. Duplicate keys, according to the comparator
500     * (which might be the keys' natural order), are not allowed, and will cause {@link #build} to
501     * fail.
502     *
503     * @throws NullPointerException if any key, value, or entry is null
504     * @since 19.0
505     */
506    @CanIgnoreReturnValue
507    @Beta
508    @Override
509    public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
510      super.putAll(entries);
511      return this;
512    }
513
514    /**
515     * Throws an {@code UnsupportedOperationException}.
516     *
517     * @since 19.0
518     * @deprecated Unsupported by ImmutableSortedMap.Builder.
519     */
520    @CanIgnoreReturnValue
521    @Beta
522    @Override
523    @Deprecated
524    @DoNotCall("Always throws UnsupportedOperationException")
525    public final Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) {
526      throw new UnsupportedOperationException("Not available on ImmutableSortedMap.Builder");
527    }
528
529    @Override
530    Builder<K, V> combine(ImmutableMap.Builder<K, V> other) {
531      super.combine(other);
532      return this;
533    }
534
535    /**
536     * Returns a newly-created immutable sorted map.
537     *
538     * @throws IllegalArgumentException if any two keys are equal according to the comparator (which
539     *     might be the keys' natural order)
540     */
541    @Override
542    public ImmutableSortedMap<K, V> build() {
543      switch (size) {
544        case 0:
545          return emptyMap(comparator);
546        case 1:
547          return of(comparator, entries[0].getKey(), entries[0].getValue());
548        default:
549          return fromEntries(comparator, false, entries, size);
550      }
551    }
552  }
553
554  private final transient RegularImmutableSortedSet<K> keySet;
555  private final transient ImmutableList<V> valueList;
556  private transient ImmutableSortedMap<K, V> descendingMap;
557
558  ImmutableSortedMap(RegularImmutableSortedSet<K> keySet, ImmutableList<V> valueList) {
559    this(keySet, valueList, null);
560  }
561
562  ImmutableSortedMap(
563      RegularImmutableSortedSet<K> keySet,
564      ImmutableList<V> valueList,
565      ImmutableSortedMap<K, V> descendingMap) {
566    this.keySet = keySet;
567    this.valueList = valueList;
568    this.descendingMap = descendingMap;
569  }
570
571  @Override
572  public int size() {
573    return valueList.size();
574  }
575
576  @Override
577  public void forEach(BiConsumer<? super K, ? super V> action) {
578    checkNotNull(action);
579    ImmutableList<K> keyList = keySet.asList();
580    for (int i = 0; i < size(); i++) {
581      action.accept(keyList.get(i), valueList.get(i));
582    }
583  }
584
585  @Override
586  public V get(@Nullable Object key) {
587    int index = keySet.indexOf(key);
588    return (index == -1) ? null : valueList.get(index);
589  }
590
591  @Override
592  boolean isPartialView() {
593    return keySet.isPartialView() || valueList.isPartialView();
594  }
595
596  /** Returns an immutable set of the mappings in this map, sorted by the key ordering. */
597  @Override
598  public ImmutableSet<Entry<K, V>> entrySet() {
599    return super.entrySet();
600  }
601
602  @Override
603  ImmutableSet<Entry<K, V>> createEntrySet() {
604    class EntrySet extends ImmutableMapEntrySet<K, V> {
605      @Override
606      public UnmodifiableIterator<Entry<K, V>> iterator() {
607        return asList().iterator();
608      }
609
610      @Override
611      public Spliterator<Entry<K, V>> spliterator() {
612        return asList().spliterator();
613      }
614
615      @Override
616      public void forEach(Consumer<? super Entry<K, V>> action) {
617        asList().forEach(action);
618      }
619
620      @Override
621      ImmutableList<Entry<K, V>> createAsList() {
622        return new ImmutableAsList<Entry<K, V>>() {
623          @Override
624          public Entry<K, V> get(int index) {
625            return new AbstractMap.SimpleImmutableEntry<>(
626                keySet.asList().get(index), valueList.get(index));
627          }
628
629          @Override
630          public Spliterator<Entry<K, V>> spliterator() {
631            return CollectSpliterators.indexed(
632                size(), ImmutableSet.SPLITERATOR_CHARACTERISTICS, this::get);
633          }
634
635          @Override
636          ImmutableCollection<Entry<K, V>> delegateCollection() {
637            return EntrySet.this;
638          }
639        };
640      }
641
642      @Override
643      ImmutableMap<K, V> map() {
644        return ImmutableSortedMap.this;
645      }
646    }
647    return isEmpty() ? ImmutableSet.<Entry<K, V>>of() : new EntrySet();
648  }
649
650  /** Returns an immutable sorted set of the keys in this map. */
651  @Override
652  public ImmutableSortedSet<K> keySet() {
653    return keySet;
654  }
655
656  @Override
657  ImmutableSet<K> createKeySet() {
658    throw new AssertionError("should never be called");
659  }
660
661  /**
662   * Returns an immutable collection of the values in this map, sorted by the ordering of the
663   * corresponding keys.
664   */
665  @Override
666  public ImmutableCollection<V> values() {
667    return valueList;
668  }
669
670  @Override
671  ImmutableCollection<V> createValues() {
672    throw new AssertionError("should never be called");
673  }
674
675  /**
676   * Returns the comparator that orders the keys, which is {@link Ordering#natural()} when the
677   * natural ordering of the keys is used. Note that its behavior is not consistent with {@link
678   * TreeMap#comparator()}, which returns {@code null} to indicate natural ordering.
679   */
680  @Override
681  public Comparator<? super K> comparator() {
682    return keySet().comparator();
683  }
684
685  @Override
686  public K firstKey() {
687    return keySet().first();
688  }
689
690  @Override
691  public K lastKey() {
692    return keySet().last();
693  }
694
695  private ImmutableSortedMap<K, V> getSubMap(int fromIndex, int toIndex) {
696    if (fromIndex == 0 && toIndex == size()) {
697      return this;
698    } else if (fromIndex == toIndex) {
699      return emptyMap(comparator());
700    } else {
701      return new ImmutableSortedMap<>(
702          keySet.getSubSet(fromIndex, toIndex), valueList.subList(fromIndex, toIndex));
703    }
704  }
705
706  /**
707   * This method returns a {@code ImmutableSortedMap}, consisting of the entries whose keys are less
708   * than {@code toKey}.
709   *
710   * <p>The {@link SortedMap#headMap} documentation states that a submap of a submap throws an
711   * {@link IllegalArgumentException} if passed a {@code toKey} greater than an earlier {@code
712   * toKey}. However, this method doesn't throw an exception in that situation, but instead keeps
713   * the original {@code toKey}.
714   */
715  @Override
716  public ImmutableSortedMap<K, V> headMap(K toKey) {
717    return headMap(toKey, false);
718  }
719
720  /**
721   * This method returns a {@code ImmutableSortedMap}, consisting of the entries whose keys are less
722   * than (or equal to, if {@code inclusive}) {@code toKey}.
723   *
724   * <p>The {@link SortedMap#headMap} documentation states that a submap of a submap throws an
725   * {@link IllegalArgumentException} if passed a {@code toKey} greater than an earlier {@code
726   * toKey}. However, this method doesn't throw an exception in that situation, but instead keeps
727   * the original {@code toKey}.
728   *
729   * @since 12.0
730   */
731  @Override
732  public ImmutableSortedMap<K, V> headMap(K toKey, boolean inclusive) {
733    return getSubMap(0, keySet.headIndex(checkNotNull(toKey), inclusive));
734  }
735
736  /**
737   * This method returns a {@code ImmutableSortedMap}, consisting of the entries whose keys ranges
738   * from {@code fromKey}, inclusive, to {@code toKey}, exclusive.
739   *
740   * <p>The {@link SortedMap#subMap} documentation states that a submap of a submap throws an {@link
741   * IllegalArgumentException} if passed a {@code fromKey} less than an earlier {@code fromKey}.
742   * However, this method doesn't throw an exception in that situation, but instead keeps the
743   * original {@code fromKey}. Similarly, this method keeps the original {@code toKey}, instead of
744   * throwing an exception, if passed a {@code toKey} greater than an earlier {@code toKey}.
745   */
746  @Override
747  public ImmutableSortedMap<K, V> subMap(K fromKey, K toKey) {
748    return subMap(fromKey, true, toKey, false);
749  }
750
751  /**
752   * This method returns a {@code ImmutableSortedMap}, consisting of the entries whose keys ranges
753   * from {@code fromKey} to {@code toKey}, inclusive or exclusive as indicated by the boolean
754   * flags.
755   *
756   * <p>The {@link SortedMap#subMap} documentation states that a submap of a submap throws an {@link
757   * IllegalArgumentException} if passed a {@code fromKey} less than an earlier {@code fromKey}.
758   * However, this method doesn't throw an exception in that situation, but instead keeps the
759   * original {@code fromKey}. Similarly, this method keeps the original {@code toKey}, instead of
760   * throwing an exception, if passed a {@code toKey} greater than an earlier {@code toKey}.
761   *
762   * @since 12.0
763   */
764  @Override
765  public ImmutableSortedMap<K, V> subMap(
766      K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
767    checkNotNull(fromKey);
768    checkNotNull(toKey);
769    checkArgument(
770        comparator().compare(fromKey, toKey) <= 0,
771        "expected fromKey <= toKey but %s > %s",
772        fromKey,
773        toKey);
774    return headMap(toKey, toInclusive).tailMap(fromKey, fromInclusive);
775  }
776
777  /**
778   * This method returns a {@code ImmutableSortedMap}, consisting of the entries whose keys are
779   * greater than or equals to {@code fromKey}.
780   *
781   * <p>The {@link SortedMap#tailMap} documentation states that a submap of a submap throws an
782   * {@link IllegalArgumentException} if passed a {@code fromKey} less than an earlier {@code
783   * fromKey}. However, this method doesn't throw an exception in that situation, but instead keeps
784   * the original {@code fromKey}.
785   */
786  @Override
787  public ImmutableSortedMap<K, V> tailMap(K fromKey) {
788    return tailMap(fromKey, true);
789  }
790
791  /**
792   * This method returns a {@code ImmutableSortedMap}, consisting of the entries whose keys are
793   * greater than (or equal to, if {@code inclusive}) {@code fromKey}.
794   *
795   * <p>The {@link SortedMap#tailMap} documentation states that a submap of a submap throws an
796   * {@link IllegalArgumentException} if passed a {@code fromKey} less than an earlier {@code
797   * fromKey}. However, this method doesn't throw an exception in that situation, but instead keeps
798   * the original {@code fromKey}.
799   *
800   * @since 12.0
801   */
802  @Override
803  public ImmutableSortedMap<K, V> tailMap(K fromKey, boolean inclusive) {
804    return getSubMap(keySet.tailIndex(checkNotNull(fromKey), inclusive), size());
805  }
806
807  @Override
808  public Entry<K, V> lowerEntry(K key) {
809    return headMap(key, false).lastEntry();
810  }
811
812  @Override
813  public K lowerKey(K key) {
814    return keyOrNull(lowerEntry(key));
815  }
816
817  @Override
818  public Entry<K, V> floorEntry(K key) {
819    return headMap(key, true).lastEntry();
820  }
821
822  @Override
823  public K floorKey(K key) {
824    return keyOrNull(floorEntry(key));
825  }
826
827  @Override
828  public Entry<K, V> ceilingEntry(K key) {
829    return tailMap(key, true).firstEntry();
830  }
831
832  @Override
833  public K ceilingKey(K key) {
834    return keyOrNull(ceilingEntry(key));
835  }
836
837  @Override
838  public Entry<K, V> higherEntry(K key) {
839    return tailMap(key, false).firstEntry();
840  }
841
842  @Override
843  public K higherKey(K key) {
844    return keyOrNull(higherEntry(key));
845  }
846
847  @Override
848  public Entry<K, V> firstEntry() {
849    return isEmpty() ? null : entrySet().asList().get(0);
850  }
851
852  @Override
853  public Entry<K, V> lastEntry() {
854    return isEmpty() ? null : entrySet().asList().get(size() - 1);
855  }
856
857  /**
858   * Guaranteed to throw an exception and leave the map unmodified.
859   *
860   * @throws UnsupportedOperationException always
861   * @deprecated Unsupported operation.
862   */
863  @CanIgnoreReturnValue
864  @Deprecated
865  @Override
866  @DoNotCall("Always throws UnsupportedOperationException")
867  public final Entry<K, V> pollFirstEntry() {
868    throw new UnsupportedOperationException();
869  }
870
871  /**
872   * Guaranteed to throw an exception and leave the map unmodified.
873   *
874   * @throws UnsupportedOperationException always
875   * @deprecated Unsupported operation.
876   */
877  @CanIgnoreReturnValue
878  @Deprecated
879  @Override
880  @DoNotCall("Always throws UnsupportedOperationException")
881  public final Entry<K, V> pollLastEntry() {
882    throw new UnsupportedOperationException();
883  }
884
885  @Override
886  public ImmutableSortedMap<K, V> descendingMap() {
887    // TODO(kevinb): the descendingMap is never actually cached at all. Either it should be or the
888    // code below simplified.
889    ImmutableSortedMap<K, V> result = descendingMap;
890    if (result == null) {
891      if (isEmpty()) {
892        return result = emptyMap(Ordering.from(comparator()).reverse());
893      } else {
894        return result =
895            new ImmutableSortedMap<>(
896                (RegularImmutableSortedSet<K>) keySet.descendingSet(), valueList.reverse(), this);
897      }
898    }
899    return result;
900  }
901
902  @Override
903  public ImmutableSortedSet<K> navigableKeySet() {
904    return keySet;
905  }
906
907  @Override
908  public ImmutableSortedSet<K> descendingKeySet() {
909    return keySet.descendingSet();
910  }
911
912  /**
913   * Serialized type for all ImmutableSortedMap instances. It captures the logical contents and they
914   * are reconstructed using public factory methods. This ensures that the implementation types
915   * remain as implementation details.
916   */
917  private static class SerializedForm<K, V> extends ImmutableMap.SerializedForm<K, V> {
918    private final Comparator<? super K> comparator;
919
920    SerializedForm(ImmutableSortedMap<K, V> sortedMap) {
921      super(sortedMap);
922      comparator = sortedMap.comparator();
923    }
924
925    @Override
926    Builder<K, V> makeBuilder(int size) {
927      return new Builder<>(comparator);
928    }
929
930    private static final long serialVersionUID = 0;
931  }
932
933  @Override
934  Object writeReplace() {
935    return new SerializedForm<>(this);
936  }
937
938  // This class is never actually serialized directly, but we have to make the
939  // warning go away (and suppressing would suppress for all nested classes too)
940  private static final long serialVersionUID = 0;
941}