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
017 package com.google.common.collect;
018
019 import static com.google.common.base.Preconditions.checkArgument;
020 import static com.google.common.base.Preconditions.checkNotNull;
021 import static com.google.common.collect.Maps.keyOrNull;
022
023 import com.google.common.annotations.GwtCompatible;
024
025 import java.util.Arrays;
026 import java.util.Collection;
027 import java.util.Collections;
028 import java.util.Comparator;
029 import java.util.List;
030 import java.util.Map;
031 import java.util.SortedMap;
032 import java.util.TreeMap;
033
034 import javax.annotation.Nullable;
035
036 /**
037 * An immutable {@link SortedMap}. Does not permit null keys or values.
038 *
039 * <p>Unlike {@link Collections#unmodifiableSortedMap}, which is a <i>view</i>
040 * of a separate map which can still change, an instance of {@code
041 * ImmutableSortedMap} contains its own data and will <i>never</i> change.
042 * {@code ImmutableSortedMap} is convenient for {@code public static final} maps
043 * ("constant maps") and also lets you easily make a "defensive copy" of a map
044 * provided to your class by a caller.
045 *
046 * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
047 * it has no public or protected constructors. Thus, instances of this class are
048 * guaranteed to be immutable.
049 *
050 * <p>See the Guava User Guide article on <a href=
051 * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
052 * immutable collections</a>.
053 *
054 * @author Jared Levy
055 * @author Louis Wasserman
056 * @since 2.0 (imported from Google Collections Library; implements {@code
057 * NavigableMap} since 12.0)
058 */
059 @GwtCompatible(serializable = true, emulated = true)
060 public abstract class ImmutableSortedMap<K, V>
061 extends ImmutableSortedMapFauxverideShim<K, V> implements SortedMap<K, V> {
062 /*
063 * TODO(kevinb): Confirm that ImmutableSortedMap is faster to construct and
064 * uses less memory than TreeMap; then say so in the class Javadoc.
065 */
066 private static final Comparator<Comparable> NATURAL_ORDER = Ordering.natural();
067
068 private static final ImmutableSortedMap<Comparable, Object> NATURAL_EMPTY_MAP =
069 new EmptyImmutableSortedMap<Comparable, Object>(NATURAL_ORDER);
070
071 static <K, V> ImmutableSortedMap<K, V> emptyMap(Comparator<? super K> comparator) {
072 if (Ordering.natural().equals(comparator)) {
073 return of();
074 } else {
075 return new EmptyImmutableSortedMap<K, V>(comparator);
076 }
077 }
078
079 static <K, V> ImmutableSortedMap<K, V> fromSortedEntries(
080 Comparator<? super K> comparator,
081 Collection<? extends Entry<? extends K, ? extends V>> entries) {
082 if (entries.isEmpty()) {
083 return emptyMap(comparator);
084 }
085
086 ImmutableList.Builder<K> keyBuilder = ImmutableList.builder();
087 ImmutableList.Builder<V> valueBuilder = ImmutableList.builder();
088 for (Entry<? extends K, ? extends V> entry : entries) {
089 keyBuilder.add(entry.getKey());
090 valueBuilder.add(entry.getValue());
091 }
092
093 return new RegularImmutableSortedMap<K, V>(
094 new RegularImmutableSortedSet<K>(keyBuilder.build(), comparator),
095 valueBuilder.build());
096 }
097
098 static <K, V> ImmutableSortedMap<K, V> from(
099 ImmutableSortedSet<K> keySet, ImmutableList<V> valueList) {
100 if (keySet.isEmpty()) {
101 return emptyMap(keySet.comparator());
102 } else {
103 return new RegularImmutableSortedMap<K, V>(
104 (RegularImmutableSortedSet<K>) keySet,
105 valueList);
106 }
107 }
108
109 /**
110 * Returns the empty sorted map.
111 */
112 @SuppressWarnings("unchecked")
113 // unsafe, comparator() returns a comparator on the specified type
114 // TODO(kevinb): evaluate whether or not of().comparator() should return null
115 public static <K, V> ImmutableSortedMap<K, V> of() {
116 return (ImmutableSortedMap<K, V>) NATURAL_EMPTY_MAP;
117 }
118
119 /**
120 * Returns an immutable map containing a single entry.
121 */
122 public static <K extends Comparable<? super K>, V>
123 ImmutableSortedMap<K, V> of(K k1, V v1) {
124 return from(ImmutableSortedSet.of(k1), ImmutableList.of(v1));
125 }
126
127 /**
128 * Returns an immutable sorted map containing the given entries, sorted by the
129 * natural ordering of their keys.
130 *
131 * @throws IllegalArgumentException if the two keys are equal according to
132 * their natural ordering
133 */
134 public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
135 of(K k1, V v1, K k2, V v2) {
136 return new Builder<K, V>(Ordering.natural())
137 .put(k1, v1).put(k2, v2).build();
138 }
139
140 /**
141 * Returns an immutable sorted map containing the given entries, sorted by the
142 * natural ordering of their keys.
143 *
144 * @throws IllegalArgumentException if any two keys are equal according to
145 * their natural ordering
146 */
147 public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
148 of(K k1, V v1, K k2, V v2, K k3, V v3) {
149 return new Builder<K, V>(Ordering.natural())
150 .put(k1, v1).put(k2, v2).put(k3, v3).build();
151 }
152
153 /**
154 * Returns an immutable sorted map containing the given entries, sorted by the
155 * natural ordering of their keys.
156 *
157 * @throws IllegalArgumentException if any two keys are equal according to
158 * their natural ordering
159 */
160 public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
161 of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
162 return new Builder<K, V>(Ordering.natural())
163 .put(k1, v1).put(k2, v2).put(k3, v3).put(k4, v4).build();
164 }
165
166 /**
167 * Returns an immutable sorted map containing the given entries, sorted by the
168 * natural ordering of their keys.
169 *
170 * @throws IllegalArgumentException if any two keys are equal according to
171 * their natural ordering
172 */
173 public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
174 of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
175 return new Builder<K, V>(Ordering.natural())
176 .put(k1, v1).put(k2, v2).put(k3, v3).put(k4, v4).put(k5, v5).build();
177 }
178
179 /**
180 * Returns an immutable map containing the same entries as {@code map}, sorted
181 * by the natural ordering of the keys.
182 *
183 * <p>Despite the method name, this method attempts to avoid actually copying
184 * the data when it is safe to do so. The exact circumstances under which a
185 * copy will or will not be performed are undocumented and subject to change.
186 *
187 * <p>This method is not type-safe, as it may be called on a map with keys
188 * that are not mutually comparable.
189 *
190 * @throws ClassCastException if the keys in {@code map} are not mutually
191 * comparable
192 * @throws NullPointerException if any key or value in {@code map} is null
193 * @throws IllegalArgumentException if any two keys are equal according to
194 * their natural ordering
195 */
196 public static <K, V> ImmutableSortedMap<K, V> copyOf(
197 Map<? extends K, ? extends V> map) {
198 // Hack around K not being a subtype of Comparable.
199 // Unsafe, see ImmutableSortedSetFauxverideShim.
200 @SuppressWarnings("unchecked")
201 Ordering<K> naturalOrder = (Ordering<K>) Ordering.<Comparable>natural();
202 return copyOfInternal(map, naturalOrder);
203 }
204
205 /**
206 * Returns an immutable map containing the same entries as {@code map}, with
207 * keys sorted by the provided comparator.
208 *
209 * <p>Despite the method name, this method attempts to avoid actually copying
210 * the data when it is safe to do so. The exact circumstances under which a
211 * copy will or will not be performed are undocumented and subject to change.
212 *
213 * @throws NullPointerException if any key or value in {@code map} is null
214 * @throws IllegalArgumentException if any two keys are equal according to the
215 * comparator
216 */
217 public static <K, V> ImmutableSortedMap<K, V> copyOf(
218 Map<? extends K, ? extends V> map, Comparator<? super K> comparator) {
219 return copyOfInternal(map, checkNotNull(comparator));
220 }
221
222 /**
223 * Returns an immutable map containing the same entries as the provided sorted
224 * map, with the same ordering.
225 *
226 * <p>Despite the method name, this method attempts to avoid actually copying
227 * the data when it is safe to do so. The exact circumstances under which a
228 * copy will or will not be performed are undocumented and subject to change.
229 *
230 * @throws NullPointerException if any key or value in {@code map} is null
231 */
232 @SuppressWarnings("unchecked")
233 public static <K, V> ImmutableSortedMap<K, V> copyOfSorted(
234 SortedMap<K, ? extends V> map) {
235 Comparator<? super K> comparator = map.comparator();
236 if (comparator == null) {
237 // If map has a null comparator, the keys should have a natural ordering,
238 // even though K doesn't explicitly implement Comparable.
239 comparator = (Comparator<? super K>) NATURAL_ORDER;
240 }
241 return copyOfInternal(map, comparator);
242 }
243
244 private static <K, V> ImmutableSortedMap<K, V> copyOfInternal(
245 Map<? extends K, ? extends V> map, Comparator<? super K> comparator) {
246 boolean sameComparator = false;
247 if (map instanceof SortedMap) {
248 SortedMap<?, ?> sortedMap = (SortedMap<?, ?>) map;
249 Comparator<?> comparator2 = sortedMap.comparator();
250 sameComparator = (comparator2 == null)
251 ? comparator == NATURAL_ORDER
252 : comparator.equals(comparator2);
253 }
254
255 if (sameComparator && (map instanceof ImmutableSortedMap)) {
256 // TODO(kevinb): Prove that this cast is safe, even though
257 // Collections.unmodifiableSortedMap requires the same key type.
258 @SuppressWarnings("unchecked")
259 ImmutableSortedMap<K, V> kvMap = (ImmutableSortedMap<K, V>) map;
260 if (!kvMap.isPartialView()) {
261 return kvMap;
262 }
263 }
264
265 // "adding" type params to an array of a raw type should be safe as
266 // long as no one can ever cast that same array instance back to a
267 // raw type.
268 @SuppressWarnings("unchecked")
269 Entry<K, V>[] entries = map.entrySet().toArray(new Entry[0]);
270
271 for (int i = 0; i < entries.length; i++) {
272 Entry<K, V> entry = entries[i];
273 entries[i] = entryOf(entry.getKey(), entry.getValue());
274 }
275
276 List<Entry<K, V>> list = Arrays.asList(entries);
277
278 if (!sameComparator) {
279 sortEntries(list, comparator);
280 validateEntries(list, comparator);
281 }
282
283 return fromSortedEntries(comparator, list);
284 }
285
286 private static <K, V> void sortEntries(
287 List<Entry<K, V>> entries, final Comparator<? super K> comparator) {
288 Comparator<Entry<K, V>> entryComparator = new Comparator<Entry<K, V>>() {
289
290 public int compare(Entry<K, V> entry1, Entry<K, V> entry2) {
291 return comparator.compare(entry1.getKey(), entry2.getKey());
292 }
293 };
294
295 Collections.sort(entries, entryComparator);
296 }
297
298 private static <K, V> void validateEntries(List<Entry<K, V>> entries,
299 Comparator<? super K> comparator) {
300 for (int i = 1; i < entries.size(); i++) {
301 if (comparator.compare(
302 entries.get(i - 1).getKey(), entries.get(i).getKey()) == 0) {
303 throw new IllegalArgumentException(
304 "Duplicate keys in mappings " + entries.get(i - 1) + " and "
305 + entries.get(i));
306 }
307 }
308 }
309
310 /**
311 * Returns a builder that creates immutable sorted maps whose keys are
312 * ordered by their natural ordering. The sorted maps use {@link
313 * Ordering#natural()} as the comparator.
314 *
315 * <p>Note: the type parameter {@code K} extends {@code Comparable<K>} rather
316 * than {@code Comparable<? super K>} as a workaround for javac <a
317 * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6468354">bug
318 * 6468354</a>.
319 */
320 public static <K extends Comparable<K>, V> Builder<K, V> naturalOrder() {
321 return new Builder<K, V>(Ordering.natural());
322 }
323
324 /**
325 * Returns a builder that creates immutable sorted maps with an explicit
326 * comparator. If the comparator has a more general type than the map's keys,
327 * such as creating a {@code SortedMap<Integer, String>} with a {@code
328 * Comparator<Number>}, use the {@link Builder} constructor instead.
329 *
330 * @throws NullPointerException if {@code comparator} is null
331 */
332 public static <K, V> Builder<K, V> orderedBy(Comparator<K> comparator) {
333 return new Builder<K, V>(comparator);
334 }
335
336 /**
337 * Returns a builder that creates immutable sorted maps whose keys are
338 * ordered by the reverse of their natural ordering.
339 *
340 * <p>Note: the type parameter {@code K} extends {@code Comparable<K>} rather
341 * than {@code Comparable<? super K>} as a workaround for javac <a
342 * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6468354">bug
343 * 6468354</a>.
344 */
345 public static <K extends Comparable<K>, V> Builder<K, V> reverseOrder() {
346 return new Builder<K, V>(Ordering.natural().reverse());
347 }
348
349 /**
350 * A builder for creating immutable sorted map instances, especially {@code
351 * public static final} maps ("constant maps"). Example: <pre> {@code
352 *
353 * static final ImmutableSortedMap<Integer, String> INT_TO_WORD =
354 * new ImmutableSortedMap.Builder<Integer, String>(Ordering.natural())
355 * .put(1, "one")
356 * .put(2, "two")
357 * .put(3, "three")
358 * .build();}</pre>
359 *
360 * For <i>small</i> immutable sorted maps, the {@code ImmutableSortedMap.of()}
361 * methods are even more convenient.
362 *
363 * <p>Builder instances can be reused - it is safe to call {@link #build}
364 * multiple times to build multiple maps in series. Each map is a superset of
365 * the maps created before it.
366 *
367 * @since 2.0 (imported from Google Collections Library)
368 */
369 public static class Builder<K, V> extends ImmutableMap.Builder<K, V> {
370 private final Comparator<? super K> comparator;
371
372 /**
373 * Creates a new builder. The returned builder is equivalent to the builder
374 * generated by {@link ImmutableSortedMap#orderedBy}.
375 */
376 public Builder(Comparator<? super K> comparator) {
377 this.comparator = checkNotNull(comparator);
378 }
379
380 /**
381 * Associates {@code key} with {@code value} in the built map. Duplicate
382 * keys, according to the comparator (which might be the keys' natural
383 * order), are not allowed, and will cause {@link #build} to fail.
384 */
385
386 @Override
387 public Builder<K, V> put(K key, V value) {
388 entries.add(entryOf(key, value));
389 return this;
390 }
391
392 /**
393 * Adds the given {@code entry} to the map, making it immutable if
394 * necessary. Duplicate keys, according to the comparator (which might be
395 * the keys' natural order), are not allowed, and will cause {@link #build}
396 * to fail.
397 *
398 * @since 11.0
399 */
400
401 @Override
402 public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
403 super.put(entry);
404 return this;
405 }
406
407 /**
408 * Associates all of the given map's keys and values in the built map.
409 * Duplicate keys, according to the comparator (which might be the keys'
410 * natural order), are not allowed, and will cause {@link #build} to fail.
411 *
412 * @throws NullPointerException if any key or value in {@code map} is null
413 */
414
415 @Override
416 public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
417 for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
418 put(entry.getKey(), entry.getValue());
419 }
420 return this;
421 }
422
423 /**
424 * Returns a newly-created immutable sorted map.
425 *
426 * @throws IllegalArgumentException if any two keys are equal according to
427 * the comparator (which might be the keys' natural order)
428 */
429
430 @Override
431 public ImmutableSortedMap<K, V> build() {
432 sortEntries(entries, comparator);
433 validateEntries(entries, comparator);
434 return fromSortedEntries(comparator, entries);
435 }
436 }
437
438 ImmutableSortedMap() {
439 }
440
441 ImmutableSortedMap(ImmutableSortedMap<K, V> descendingMap) {
442 this.descendingMap = descendingMap;
443 }
444
445 public int size() {
446 return values().size();
447 }
448
449 @Override
450 public boolean containsValue(@Nullable Object value) {
451 return values().contains(value);
452 }
453
454 @Override
455 boolean isPartialView() {
456 return keySet().isPartialView() || values().isPartialView();
457 }
458
459 /**
460 * Returns an immutable set of the mappings in this map, sorted by the key
461 * ordering.
462 */
463
464 @Override
465 public ImmutableSet<Entry<K, V>> entrySet() {
466 return super.entrySet();
467 }
468
469 /**
470 * Returns an immutable sorted set of the keys in this map.
471 */
472 @Override
473 public abstract ImmutableSortedSet<K> keySet();
474
475 /**
476 * Returns an immutable collection of the values in this map, sorted by the
477 * ordering of the corresponding keys.
478 */
479 @Override
480 public abstract ImmutableCollection<V> values();
481
482 /**
483 * Returns the comparator that orders the keys, which is
484 * {@link Ordering#natural()} when the natural ordering of the keys is used.
485 * Note that its behavior is not consistent with {@link TreeMap#comparator()},
486 * which returns {@code null} to indicate natural ordering.
487 */
488 public Comparator<? super K> comparator() {
489 return keySet().comparator();
490 }
491
492 public K firstKey() {
493 return keySet().first();
494 }
495
496 public K lastKey() {
497 return keySet().last();
498 }
499
500 /**
501 * This method returns a {@code ImmutableSortedMap}, consisting of the entries
502 * whose keys are less than {@code toKey}.
503 *
504 * <p>The {@link SortedMap#headMap} documentation states that a submap of a
505 * submap throws an {@link IllegalArgumentException} if passed a {@code toKey}
506 * greater than an earlier {@code toKey}. However, this method doesn't throw
507 * an exception in that situation, but instead keeps the original {@code
508 * toKey}.
509 */
510 public ImmutableSortedMap<K, V> headMap(K toKey) {
511 return headMap(toKey, false);
512 }
513
514 /**
515 * This method returns a {@code ImmutableSortedMap}, consisting of the entries
516 * whose keys are less than (or equal to, if {@code inclusive}) {@code toKey}.
517 *
518 * <p>The {@link SortedMap#headMap} documentation states that a submap of a
519 * submap throws an {@link IllegalArgumentException} if passed a {@code toKey}
520 * greater than an earlier {@code toKey}. However, this method doesn't throw
521 * an exception in that situation, but instead keeps the original {@code
522 * toKey}.
523 *
524 * @since 12.0
525 */
526
527 public abstract ImmutableSortedMap<K, V> headMap(K toKey, boolean inclusive);
528
529 /**
530 * This method returns a {@code ImmutableSortedMap}, consisting of the entries
531 * whose keys ranges from {@code fromKey}, inclusive, to {@code toKey},
532 * exclusive.
533 *
534 * <p>The {@link SortedMap#subMap} documentation states that a submap of a
535 * submap throws an {@link IllegalArgumentException} if passed a {@code
536 * fromKey} less than an earlier {@code fromKey}. However, this method doesn't
537 * throw an exception in that situation, but instead keeps the original {@code
538 * fromKey}. Similarly, this method keeps the original {@code toKey}, instead
539 * of throwing an exception, if passed a {@code toKey} greater than an earlier
540 * {@code toKey}.
541 */
542 public ImmutableSortedMap<K, V> subMap(K fromKey, K toKey) {
543 return subMap(fromKey, true, toKey, false);
544 }
545
546 /**
547 * This method returns a {@code ImmutableSortedMap}, consisting of the entries
548 * whose keys ranges from {@code fromKey} to {@code toKey}, inclusive or
549 * exclusive as indicated by the boolean flags.
550 *
551 * <p>The {@link SortedMap#subMap} documentation states that a submap of a
552 * submap throws an {@link IllegalArgumentException} if passed a {@code
553 * fromKey} less than an earlier {@code fromKey}. However, this method doesn't
554 * throw an exception in that situation, but instead keeps the original {@code
555 * fromKey}. Similarly, this method keeps the original {@code toKey}, instead
556 * of throwing an exception, if passed a {@code toKey} greater than an earlier
557 * {@code toKey}.
558 *
559 * @since 12.0
560 */
561 public ImmutableSortedMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey,
562 boolean toInclusive) {
563 checkNotNull(fromKey);
564 checkNotNull(toKey);
565 checkArgument(comparator().compare(fromKey, toKey) <= 0,
566 "expected fromKey <= toKey but %s > %s", fromKey, toKey);
567 return headMap(toKey, toInclusive).tailMap(fromKey, fromInclusive);
568 }
569
570 /**
571 * This method returns a {@code ImmutableSortedMap}, consisting of the entries
572 * whose keys are greater than or equals to {@code fromKey}.
573 *
574 * <p>The {@link SortedMap#tailMap} documentation states that a submap of a
575 * submap throws an {@link IllegalArgumentException} if passed a {@code
576 * fromKey} less than an earlier {@code fromKey}. However, this method doesn't
577 * throw an exception in that situation, but instead keeps the original {@code
578 * fromKey}.
579 */
580 public ImmutableSortedMap<K, V> tailMap(K fromKey) {
581 return tailMap(fromKey, true);
582 }
583
584 /**
585 * This method returns a {@code ImmutableSortedMap}, consisting of the entries
586 * whose keys are greater than (or equal to, if {@code inclusive})
587 * {@code fromKey}.
588 *
589 * <p>The {@link SortedMap#tailMap} documentation states that a submap of a
590 * submap throws an {@link IllegalArgumentException} if passed a {@code
591 * fromKey} less than an earlier {@code fromKey}. However, this method doesn't
592 * throw an exception in that situation, but instead keeps the original {@code
593 * fromKey}.
594 *
595 * @since 12.0
596 */
597
598 public abstract ImmutableSortedMap<K, V> tailMap(K fromKey, boolean inclusive);
599
600 public Entry<K, V> lowerEntry(K key) {
601 return headMap(key, false).lastEntry();
602 }
603
604 public K lowerKey(K key) {
605 return keyOrNull(lowerEntry(key));
606 }
607
608 public Entry<K, V> floorEntry(K key) {
609 return headMap(key, true).lastEntry();
610 }
611
612 public K floorKey(K key) {
613 return keyOrNull(floorEntry(key));
614 }
615
616 public Entry<K, V> ceilingEntry(K key) {
617 return tailMap(key, true).firstEntry();
618 }
619
620 public K ceilingKey(K key) {
621 return keyOrNull(ceilingEntry(key));
622 }
623
624 public Entry<K, V> higherEntry(K key) {
625 return tailMap(key, false).firstEntry();
626 }
627
628 public K higherKey(K key) {
629 return keyOrNull(higherEntry(key));
630 }
631
632 public Entry<K, V> firstEntry() {
633 return isEmpty() ? null : entrySet().asList().get(0);
634 }
635
636 public Entry<K, V> lastEntry() {
637 return isEmpty() ? null : entrySet().asList().get(size() - 1);
638 }
639
640 public final Entry<K, V> pollFirstEntry() {
641 throw new UnsupportedOperationException();
642 }
643
644 public final Entry<K, V> pollLastEntry() {
645 throw new UnsupportedOperationException();
646 }
647
648 private transient ImmutableSortedMap<K, V> descendingMap;
649
650 public ImmutableSortedMap<K, V> descendingMap() {
651 ImmutableSortedMap<K, V> result = descendingMap;
652 if (result == null) {
653 result = descendingMap = createDescendingMap();
654 }
655 return result;
656 }
657
658 abstract ImmutableSortedMap<K, V> createDescendingMap();
659
660
661 public ImmutableSortedSet<K> navigableKeySet() {
662 return keySet();
663 }
664
665 public ImmutableSortedSet<K> descendingKeySet() {
666 return keySet().descendingSet();
667 }
668
669 /**
670 * Serialized type for all ImmutableSortedMap instances. It captures the
671 * logical contents and they are reconstructed using public factory methods.
672 * This ensures that the implementation types remain as implementation
673 * details.
674 */
675 private static class SerializedForm extends ImmutableMap.SerializedForm {
676 private final Comparator<Object> comparator;
677 @SuppressWarnings("unchecked")
678 SerializedForm(ImmutableSortedMap<?, ?> sortedMap) {
679 super(sortedMap);
680 comparator = (Comparator<Object>) sortedMap.comparator();
681 }
682
683 @Override
684 Object readResolve() {
685 Builder<Object, Object> builder = new Builder<Object, Object>(comparator);
686 return createMap(builder);
687 }
688 private static final long serialVersionUID = 0;
689 }
690
691
692 @Override
693 Object writeReplace() {
694 return new SerializedForm(this);
695 }
696
697 // This class is never actually serialized directly, but we have to make the
698 // warning go away (and suppressing would suppress for all nested classes too)
699 private static final long serialVersionUID = 0;
700 }