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