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}