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