Coverage Summary for Class: AbstractMapBasedMultimap (com.google.common.collect)
| Class | Method, % | Line, % |
|---|---|---|
| AbstractMapBasedMultimap | 31.4% (11/35) | 35.7% (40/112) |
| AbstractMapBasedMultimap$1 | 0% (0/2) | 0% (0/2) |
| AbstractMapBasedMultimap$2 | 0% (0/2) | 0% (0/2) |
| AbstractMapBasedMultimap$AsMap | 66.7% (8/12) | 44.8% (13/29) |
| AbstractMapBasedMultimap$AsMap$AsMapEntries | 33.3% (2/6) | 20% (2/10) |
| AbstractMapBasedMultimap$AsMap$AsMapIterator | 75% (3/4) | 50% (6/12) |
| AbstractMapBasedMultimap$Itr | 0% (0/4) | 0% (0/16) |
| AbstractMapBasedMultimap$KeySet | 0% (0/8) | 0% (0/16) |
| AbstractMapBasedMultimap$KeySet$1 | 0% (0/4) | 0% (0/10) |
| AbstractMapBasedMultimap$NavigableAsMap | 0% (0/26) | 0% (0/39) |
| AbstractMapBasedMultimap$NavigableKeySet | 0% (0/16) | 0% (0/18) |
| AbstractMapBasedMultimap$RandomAccessWrappedList | 100% (1/1) | 100% (3/3) |
| AbstractMapBasedMultimap$SortedAsMap | 0% (0/10) | 0% (0/12) |
| AbstractMapBasedMultimap$SortedKeySet | 0% (0/8) | 0% (0/9) |
| AbstractMapBasedMultimap$WrappedCollection | 33.3% (7/21) | 30.1% (28/93) |
| AbstractMapBasedMultimap$WrappedCollection$WrappedIterator | 57.1% (4/7) | 52.4% (11/21) |
| AbstractMapBasedMultimap$WrappedList | 25% (3/12) | 14% (6/43) |
| AbstractMapBasedMultimap$WrappedList$WrappedListIterator | 0% (0/9) | 0% (0/14) |
| AbstractMapBasedMultimap$WrappedNavigableSet | 0% (0/14) | 0% (0/16) |
| AbstractMapBasedMultimap$WrappedSet | 50% (1/2) | 25% (3/12) |
| AbstractMapBasedMultimap$WrappedSortedSet | 0% (0/8) | 0% (0/23) |
| Total | 19% (40/211) | 21.9% (112/512) |
1 /* 2 * Copyright (C) 2007 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.collect; 18 19 import static com.google.common.base.Preconditions.checkArgument; 20 import static com.google.common.base.Preconditions.checkNotNull; 21 import static com.google.common.collect.CollectPreconditions.checkRemove; 22 23 import com.google.common.annotations.GwtCompatible; 24 import com.google.common.collect.Maps.ViewCachingAbstractMap; 25 import com.google.j2objc.annotations.WeakOuter; 26 import java.io.Serializable; 27 import java.util.AbstractCollection; 28 import java.util.Collection; 29 import java.util.Collections; 30 import java.util.Comparator; 31 import java.util.ConcurrentModificationException; 32 import java.util.Iterator; 33 import java.util.List; 34 import java.util.ListIterator; 35 import java.util.Map; 36 import java.util.Map.Entry; 37 import java.util.NavigableMap; 38 import java.util.NavigableSet; 39 import java.util.RandomAccess; 40 import java.util.Set; 41 import java.util.SortedMap; 42 import java.util.SortedSet; 43 import java.util.Spliterator; 44 import java.util.function.BiConsumer; 45 import org.checkerframework.checker.nullness.qual.Nullable; 46 47 /** 48 * Basic implementation of the {@link Multimap} interface. This class represents a multimap as a map 49 * that associates each key with a collection of values. All methods of {@link Multimap} are 50 * supported, including those specified as optional in the interface. 51 * 52 * <p>To implement a multimap, a subclass must define the method {@link #createCollection()}, which 53 * creates an empty collection of values for a key. 54 * 55 * <p>The multimap constructor takes a map that has a single entry for each distinct key. When you 56 * insert a key-value pair with a key that isn't already in the multimap, {@code 57 * AbstractMapBasedMultimap} calls {@link #createCollection()} to create the collection of values 58 * for that key. The subclass should not call {@link #createCollection()} directly, and a new 59 * instance should be created every time the method is called. 60 * 61 * <p>For example, the subclass could pass a {@link java.util.TreeMap} during construction, and 62 * {@link #createCollection()} could return a {@link java.util.TreeSet}, in which case the 63 * multimap's iterators would propagate through the keys and values in sorted order. 64 * 65 * <p>Keys and values may be null, as long as the underlying collection classes support null 66 * elements. 67 * 68 * <p>The collections created by {@link #createCollection()} may or may not allow duplicates. If the 69 * collection, such as a {@link Set}, does not support duplicates, an added key-value pair will 70 * replace an existing pair with the same key and value, if such a pair is present. With collections 71 * like {@link List} that allow duplicates, the collection will keep the existing key-value pairs 72 * while adding a new pair. 73 * 74 * <p>This class is not threadsafe when any concurrent operations update the multimap, even if the 75 * underlying map and {@link #createCollection()} method return threadsafe classes. Concurrent read 76 * operations will work correctly. To allow concurrent update operations, wrap your multimap with a 77 * call to {@link Multimaps#synchronizedMultimap}. 78 * 79 * <p>For serialization to work, the subclass must specify explicit {@code readObject} and {@code 80 * writeObject} methods. 81 * 82 * @author Jared Levy 83 * @author Louis Wasserman 84 */ 85 @GwtCompatible 86 abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V> 87 implements Serializable { 88 /* 89 * Here's an outline of the overall design. 90 * 91 * The map variable contains the collection of values associated with each 92 * key. When a key-value pair is added to a multimap that didn't previously 93 * contain any values for that key, a new collection generated by 94 * createCollection is added to the map. That same collection instance 95 * remains in the map as long as the multimap has any values for the key. If 96 * all values for the key are removed, the key and collection are removed 97 * from the map. 98 * 99 * The get method returns a WrappedCollection, which decorates the collection 100 * in the map (if the key is present) or an empty collection (if the key is 101 * not present). When the collection delegate in the WrappedCollection is 102 * empty, the multimap may contain subsequently added values for that key. To 103 * handle that situation, the WrappedCollection checks whether map contains 104 * an entry for the provided key, and if so replaces the delegate. 105 */ 106 107 private transient Map<K, Collection<V>> map; 108 private transient int totalSize; 109 110 /** 111 * Creates a new multimap that uses the provided map. 112 * 113 * @param map place to store the mapping from each key to its corresponding values 114 * @throws IllegalArgumentException if {@code map} is not empty 115 */ 116 protected AbstractMapBasedMultimap(Map<K, Collection<V>> map) { 117 checkArgument(map.isEmpty()); 118 this.map = map; 119 } 120 121 /** Used during deserialization only. */ 122 final void setMap(Map<K, Collection<V>> map) { 123 this.map = map; 124 totalSize = 0; 125 for (Collection<V> values : map.values()) { 126 checkArgument(!values.isEmpty()); 127 totalSize += values.size(); 128 } 129 } 130 131 /** 132 * Creates an unmodifiable, empty collection of values. 133 * 134 * <p>This is used in {@link #removeAll} on an empty key. 135 */ 136 Collection<V> createUnmodifiableEmptyCollection() { 137 return unmodifiableCollectionSubclass(createCollection()); 138 } 139 140 /** 141 * Creates the collection of values for a single key. 142 * 143 * <p>Collections with weak, soft, or phantom references are not supported. Each call to {@code 144 * createCollection} should create a new instance. 145 * 146 * <p>The returned collection class determines whether duplicate key-value pairs are allowed. 147 * 148 * @return an empty collection of values 149 */ 150 abstract Collection<V> createCollection(); 151 152 /** 153 * Creates the collection of values for an explicitly provided key. By default, it simply calls 154 * {@link #createCollection()}, which is the correct behavior for most implementations. The {@link 155 * LinkedHashMultimap} class overrides it. 156 * 157 * @param key key to associate with values in the collection 158 * @return an empty collection of values 159 */ 160 Collection<V> createCollection(@Nullable K key) { 161 return createCollection(); 162 } 163 164 Map<K, Collection<V>> backingMap() { 165 return map; 166 } 167 168 // Query Operations 169 170 @Override 171 public int size() { 172 return totalSize; 173 } 174 175 @Override 176 public boolean containsKey(@Nullable Object key) { 177 return map.containsKey(key); 178 } 179 180 // Modification Operations 181 182 @Override 183 public boolean put(@Nullable K key, @Nullable V value) { 184 Collection<V> collection = map.get(key); 185 if (collection == null) { 186 collection = createCollection(key); 187 if (collection.add(value)) { 188 totalSize++; 189 map.put(key, collection); 190 return true; 191 } else { 192 throw new AssertionError("New Collection violated the Collection spec"); 193 } 194 } else if (collection.add(value)) { 195 totalSize++; 196 return true; 197 } else { 198 return false; 199 } 200 } 201 202 private Collection<V> getOrCreateCollection(@Nullable K key) { 203 Collection<V> collection = map.get(key); 204 if (collection == null) { 205 collection = createCollection(key); 206 map.put(key, collection); 207 } 208 return collection; 209 } 210 211 // Bulk Operations 212 213 /** 214 * {@inheritDoc} 215 * 216 * <p>The returned collection is immutable. 217 */ 218 @Override 219 public Collection<V> replaceValues(@Nullable K key, Iterable<? extends V> values) { 220 Iterator<? extends V> iterator = values.iterator(); 221 if (!iterator.hasNext()) { 222 return removeAll(key); 223 } 224 225 // TODO(lowasser): investigate atomic failure? 226 Collection<V> collection = getOrCreateCollection(key); 227 Collection<V> oldValues = createCollection(); 228 oldValues.addAll(collection); 229 230 totalSize -= collection.size(); 231 collection.clear(); 232 233 while (iterator.hasNext()) { 234 if (collection.add(iterator.next())) { 235 totalSize++; 236 } 237 } 238 239 return unmodifiableCollectionSubclass(oldValues); 240 } 241 242 /** 243 * {@inheritDoc} 244 * 245 * <p>The returned collection is immutable. 246 */ 247 @Override 248 public Collection<V> removeAll(@Nullable Object key) { 249 Collection<V> collection = map.remove(key); 250 251 if (collection == null) { 252 return createUnmodifiableEmptyCollection(); 253 } 254 255 Collection<V> output = createCollection(); 256 output.addAll(collection); 257 totalSize -= collection.size(); 258 collection.clear(); 259 260 return unmodifiableCollectionSubclass(output); 261 } 262 263 <E> Collection<E> unmodifiableCollectionSubclass(Collection<E> collection) { 264 return Collections.unmodifiableCollection(collection); 265 } 266 267 @Override 268 public void clear() { 269 // Clear each collection, to make previously returned collections empty. 270 for (Collection<V> collection : map.values()) { 271 collection.clear(); 272 } 273 map.clear(); 274 totalSize = 0; 275 } 276 277 // Views 278 279 /** 280 * {@inheritDoc} 281 * 282 * <p>The returned collection is not serializable. 283 */ 284 @Override 285 public Collection<V> get(@Nullable K key) { 286 Collection<V> collection = map.get(key); 287 if (collection == null) { 288 collection = createCollection(key); 289 } 290 return wrapCollection(key, collection); 291 } 292 293 /** 294 * Generates a decorated collection that remains consistent with the values in the multimap for 295 * the provided key. Changes to the multimap may alter the returned collection, and vice versa. 296 */ 297 Collection<V> wrapCollection(@Nullable K key, Collection<V> collection) { 298 return new WrappedCollection(key, collection, null); 299 } 300 301 final List<V> wrapList(@Nullable K key, List<V> list, @Nullable WrappedCollection ancestor) { 302 return (list instanceof RandomAccess) 303 ? new RandomAccessWrappedList(key, list, ancestor) 304 : new WrappedList(key, list, ancestor); 305 } 306 307 /** 308 * Collection decorator that stays in sync with the multimap values for a key. There are two kinds 309 * of wrapped collections: full and subcollections. Both have a delegate pointing to the 310 * underlying collection class. 311 * 312 * <p>Full collections, identified by a null ancestor field, contain all multimap values for a 313 * given key. Its delegate is a value in {@link AbstractMapBasedMultimap#map} whenever the 314 * delegate is non-empty. The {@code refreshIfEmpty}, {@code removeIfEmpty}, and {@code addToMap} 315 * methods ensure that the {@code WrappedCollection} and map remain consistent. 316 * 317 * <p>A subcollection, such as a sublist, contains some of the values for a given key. Its 318 * ancestor field points to the full wrapped collection with all values for the key. The 319 * subcollection {@code refreshIfEmpty}, {@code removeIfEmpty}, and {@code addToMap} methods call 320 * the corresponding methods of the full wrapped collection. 321 */ 322 @WeakOuter 323 class WrappedCollection extends AbstractCollection<V> { 324 final @Nullable K key; 325 Collection<V> delegate; 326 final @Nullable WrappedCollection ancestor; 327 final @Nullable Collection<V> ancestorDelegate; 328 329 WrappedCollection( 330 @Nullable K key, Collection<V> delegate, @Nullable WrappedCollection ancestor) { 331 this.key = key; 332 this.delegate = delegate; 333 this.ancestor = ancestor; 334 this.ancestorDelegate = (ancestor == null) ? null : ancestor.getDelegate(); 335 } 336 337 /** 338 * If the delegate collection is empty, but the multimap has values for the key, replace the 339 * delegate with the new collection for the key. 340 * 341 * <p>For a subcollection, refresh its ancestor and validate that the ancestor delegate hasn't 342 * changed. 343 */ 344 void refreshIfEmpty() { 345 if (ancestor != null) { 346 ancestor.refreshIfEmpty(); 347 if (ancestor.getDelegate() != ancestorDelegate) { 348 throw new ConcurrentModificationException(); 349 } 350 } else if (delegate.isEmpty()) { 351 Collection<V> newDelegate = map.get(key); 352 if (newDelegate != null) { 353 delegate = newDelegate; 354 } 355 } 356 } 357 358 /** 359 * If collection is empty, remove it from {@code AbstractMapBasedMultimap.this.map}. For 360 * subcollections, check whether the ancestor collection is empty. 361 */ 362 void removeIfEmpty() { 363 if (ancestor != null) { 364 ancestor.removeIfEmpty(); 365 } else if (delegate.isEmpty()) { 366 map.remove(key); 367 } 368 } 369 370 K getKey() { 371 return key; 372 } 373 374 /** 375 * Add the delegate to the map. Other {@code WrappedCollection} methods should call this method 376 * after adding elements to a previously empty collection. 377 * 378 * <p>Subcollection add the ancestor's delegate instead. 379 */ 380 void addToMap() { 381 if (ancestor != null) { 382 ancestor.addToMap(); 383 } else { 384 map.put(key, delegate); 385 } 386 } 387 388 @Override 389 public int size() { 390 refreshIfEmpty(); 391 return delegate.size(); 392 } 393 394 @Override 395 public boolean equals(@Nullable Object object) { 396 if (object == this) { 397 return true; 398 } 399 refreshIfEmpty(); 400 return delegate.equals(object); 401 } 402 403 @Override 404 public int hashCode() { 405 refreshIfEmpty(); 406 return delegate.hashCode(); 407 } 408 409 @Override 410 public String toString() { 411 refreshIfEmpty(); 412 return delegate.toString(); 413 } 414 415 Collection<V> getDelegate() { 416 return delegate; 417 } 418 419 @Override 420 public Iterator<V> iterator() { 421 refreshIfEmpty(); 422 return new WrappedIterator(); 423 } 424 425 @Override 426 public Spliterator<V> spliterator() { 427 refreshIfEmpty(); 428 return delegate.spliterator(); 429 } 430 431 /** Collection iterator for {@code WrappedCollection}. */ 432 class WrappedIterator implements Iterator<V> { 433 final Iterator<V> delegateIterator; 434 final Collection<V> originalDelegate = delegate; 435 436 WrappedIterator() { 437 delegateIterator = iteratorOrListIterator(delegate); 438 } 439 440 WrappedIterator(Iterator<V> delegateIterator) { 441 this.delegateIterator = delegateIterator; 442 } 443 444 /** 445 * If the delegate changed since the iterator was created, the iterator is no longer valid. 446 */ 447 void validateIterator() { 448 refreshIfEmpty(); 449 if (delegate != originalDelegate) { 450 throw new ConcurrentModificationException(); 451 } 452 } 453 454 @Override 455 public boolean hasNext() { 456 validateIterator(); 457 return delegateIterator.hasNext(); 458 } 459 460 @Override 461 public V next() { 462 validateIterator(); 463 return delegateIterator.next(); 464 } 465 466 @Override 467 public void remove() { 468 delegateIterator.remove(); 469 totalSize--; 470 removeIfEmpty(); 471 } 472 473 Iterator<V> getDelegateIterator() { 474 validateIterator(); 475 return delegateIterator; 476 } 477 } 478 479 @Override 480 public boolean add(V value) { 481 refreshIfEmpty(); 482 boolean wasEmpty = delegate.isEmpty(); 483 boolean changed = delegate.add(value); 484 if (changed) { 485 totalSize++; 486 if (wasEmpty) { 487 addToMap(); 488 } 489 } 490 return changed; 491 } 492 493 WrappedCollection getAncestor() { 494 return ancestor; 495 } 496 497 // The following methods are provided for better performance. 498 499 @Override 500 public boolean addAll(Collection<? extends V> collection) { 501 if (collection.isEmpty()) { 502 return false; 503 } 504 int oldSize = size(); // calls refreshIfEmpty 505 boolean changed = delegate.addAll(collection); 506 if (changed) { 507 int newSize = delegate.size(); 508 totalSize += (newSize - oldSize); 509 if (oldSize == 0) { 510 addToMap(); 511 } 512 } 513 return changed; 514 } 515 516 @Override 517 public boolean contains(Object o) { 518 refreshIfEmpty(); 519 return delegate.contains(o); 520 } 521 522 @Override 523 public boolean containsAll(Collection<?> c) { 524 refreshIfEmpty(); 525 return delegate.containsAll(c); 526 } 527 528 @Override 529 public void clear() { 530 int oldSize = size(); // calls refreshIfEmpty 531 if (oldSize == 0) { 532 return; 533 } 534 delegate.clear(); 535 totalSize -= oldSize; 536 removeIfEmpty(); // maybe shouldn't be removed if this is a sublist 537 } 538 539 @Override 540 public boolean remove(Object o) { 541 refreshIfEmpty(); 542 boolean changed = delegate.remove(o); 543 if (changed) { 544 totalSize--; 545 removeIfEmpty(); 546 } 547 return changed; 548 } 549 550 @Override 551 public boolean removeAll(Collection<?> c) { 552 if (c.isEmpty()) { 553 return false; 554 } 555 int oldSize = size(); // calls refreshIfEmpty 556 boolean changed = delegate.removeAll(c); 557 if (changed) { 558 int newSize = delegate.size(); 559 totalSize += (newSize - oldSize); 560 removeIfEmpty(); 561 } 562 return changed; 563 } 564 565 @Override 566 public boolean retainAll(Collection<?> c) { 567 checkNotNull(c); 568 int oldSize = size(); // calls refreshIfEmpty 569 boolean changed = delegate.retainAll(c); 570 if (changed) { 571 int newSize = delegate.size(); 572 totalSize += (newSize - oldSize); 573 removeIfEmpty(); 574 } 575 return changed; 576 } 577 } 578 579 private static <E> Iterator<E> iteratorOrListIterator(Collection<E> collection) { 580 return (collection instanceof List) 581 ? ((List<E>) collection).listIterator() 582 : collection.iterator(); 583 } 584 585 /** Set decorator that stays in sync with the multimap values for a key. */ 586 @WeakOuter 587 class WrappedSet extends WrappedCollection implements Set<V> { 588 WrappedSet(@Nullable K key, Set<V> delegate) { 589 super(key, delegate, null); 590 } 591 592 @Override 593 public boolean removeAll(Collection<?> c) { 594 if (c.isEmpty()) { 595 return false; 596 } 597 int oldSize = size(); // calls refreshIfEmpty 598 599 // Guava issue 1013: AbstractSet and most JDK set implementations are 600 // susceptible to quadratic removeAll performance on lists; 601 // use a slightly smarter implementation here 602 boolean changed = Sets.removeAllImpl((Set<V>) delegate, c); 603 if (changed) { 604 int newSize = delegate.size(); 605 totalSize += (newSize - oldSize); 606 removeIfEmpty(); 607 } 608 return changed; 609 } 610 } 611 612 /** SortedSet decorator that stays in sync with the multimap values for a key. */ 613 @WeakOuter 614 class WrappedSortedSet extends WrappedCollection implements SortedSet<V> { 615 WrappedSortedSet(@Nullable K key, SortedSet<V> delegate, @Nullable WrappedCollection ancestor) { 616 super(key, delegate, ancestor); 617 } 618 619 SortedSet<V> getSortedSetDelegate() { 620 return (SortedSet<V>) getDelegate(); 621 } 622 623 @Override 624 public Comparator<? super V> comparator() { 625 return getSortedSetDelegate().comparator(); 626 } 627 628 @Override 629 public V first() { 630 refreshIfEmpty(); 631 return getSortedSetDelegate().first(); 632 } 633 634 @Override 635 public V last() { 636 refreshIfEmpty(); 637 return getSortedSetDelegate().last(); 638 } 639 640 @Override 641 public SortedSet<V> headSet(V toElement) { 642 refreshIfEmpty(); 643 return new WrappedSortedSet( 644 getKey(), 645 getSortedSetDelegate().headSet(toElement), 646 (getAncestor() == null) ? this : getAncestor()); 647 } 648 649 @Override 650 public SortedSet<V> subSet(V fromElement, V toElement) { 651 refreshIfEmpty(); 652 return new WrappedSortedSet( 653 getKey(), 654 getSortedSetDelegate().subSet(fromElement, toElement), 655 (getAncestor() == null) ? this : getAncestor()); 656 } 657 658 @Override 659 public SortedSet<V> tailSet(V fromElement) { 660 refreshIfEmpty(); 661 return new WrappedSortedSet( 662 getKey(), 663 getSortedSetDelegate().tailSet(fromElement), 664 (getAncestor() == null) ? this : getAncestor()); 665 } 666 } 667 668 @WeakOuter 669 class WrappedNavigableSet extends WrappedSortedSet implements NavigableSet<V> { 670 WrappedNavigableSet( 671 @Nullable K key, NavigableSet<V> delegate, @Nullable WrappedCollection ancestor) { 672 super(key, delegate, ancestor); 673 } 674 675 @Override 676 NavigableSet<V> getSortedSetDelegate() { 677 return (NavigableSet<V>) super.getSortedSetDelegate(); 678 } 679 680 @Override 681 public V lower(V v) { 682 return getSortedSetDelegate().lower(v); 683 } 684 685 @Override 686 public V floor(V v) { 687 return getSortedSetDelegate().floor(v); 688 } 689 690 @Override 691 public V ceiling(V v) { 692 return getSortedSetDelegate().ceiling(v); 693 } 694 695 @Override 696 public V higher(V v) { 697 return getSortedSetDelegate().higher(v); 698 } 699 700 @Override 701 public V pollFirst() { 702 return Iterators.pollNext(iterator()); 703 } 704 705 @Override 706 public V pollLast() { 707 return Iterators.pollNext(descendingIterator()); 708 } 709 710 private NavigableSet<V> wrap(NavigableSet<V> wrapped) { 711 return new WrappedNavigableSet(key, wrapped, (getAncestor() == null) ? this : getAncestor()); 712 } 713 714 @Override 715 public NavigableSet<V> descendingSet() { 716 return wrap(getSortedSetDelegate().descendingSet()); 717 } 718 719 @Override 720 public Iterator<V> descendingIterator() { 721 return new WrappedIterator(getSortedSetDelegate().descendingIterator()); 722 } 723 724 @Override 725 public NavigableSet<V> subSet( 726 V fromElement, boolean fromInclusive, V toElement, boolean toInclusive) { 727 return wrap( 728 getSortedSetDelegate().subSet(fromElement, fromInclusive, toElement, toInclusive)); 729 } 730 731 @Override 732 public NavigableSet<V> headSet(V toElement, boolean inclusive) { 733 return wrap(getSortedSetDelegate().headSet(toElement, inclusive)); 734 } 735 736 @Override 737 public NavigableSet<V> tailSet(V fromElement, boolean inclusive) { 738 return wrap(getSortedSetDelegate().tailSet(fromElement, inclusive)); 739 } 740 } 741 742 /** List decorator that stays in sync with the multimap values for a key. */ 743 @WeakOuter 744 class WrappedList extends WrappedCollection implements List<V> { 745 WrappedList(@Nullable K key, List<V> delegate, @Nullable WrappedCollection ancestor) { 746 super(key, delegate, ancestor); 747 } 748 749 List<V> getListDelegate() { 750 return (List<V>) getDelegate(); 751 } 752 753 @Override 754 public boolean addAll(int index, Collection<? extends V> c) { 755 if (c.isEmpty()) { 756 return false; 757 } 758 int oldSize = size(); // calls refreshIfEmpty 759 boolean changed = getListDelegate().addAll(index, c); 760 if (changed) { 761 int newSize = getDelegate().size(); 762 totalSize += (newSize - oldSize); 763 if (oldSize == 0) { 764 addToMap(); 765 } 766 } 767 return changed; 768 } 769 770 @Override 771 public V get(int index) { 772 refreshIfEmpty(); 773 return getListDelegate().get(index); 774 } 775 776 @Override 777 public V set(int index, V element) { 778 refreshIfEmpty(); 779 return getListDelegate().set(index, element); 780 } 781 782 @Override 783 public void add(int index, V element) { 784 refreshIfEmpty(); 785 boolean wasEmpty = getDelegate().isEmpty(); 786 getListDelegate().add(index, element); 787 totalSize++; 788 if (wasEmpty) { 789 addToMap(); 790 } 791 } 792 793 @Override 794 public V remove(int index) { 795 refreshIfEmpty(); 796 V value = getListDelegate().remove(index); 797 totalSize--; 798 removeIfEmpty(); 799 return value; 800 } 801 802 @Override 803 public int indexOf(Object o) { 804 refreshIfEmpty(); 805 return getListDelegate().indexOf(o); 806 } 807 808 @Override 809 public int lastIndexOf(Object o) { 810 refreshIfEmpty(); 811 return getListDelegate().lastIndexOf(o); 812 } 813 814 @Override 815 public ListIterator<V> listIterator() { 816 refreshIfEmpty(); 817 return new WrappedListIterator(); 818 } 819 820 @Override 821 public ListIterator<V> listIterator(int index) { 822 refreshIfEmpty(); 823 return new WrappedListIterator(index); 824 } 825 826 @Override 827 public List<V> subList(int fromIndex, int toIndex) { 828 refreshIfEmpty(); 829 return wrapList( 830 getKey(), 831 getListDelegate().subList(fromIndex, toIndex), 832 (getAncestor() == null) ? this : getAncestor()); 833 } 834 835 /** ListIterator decorator. */ 836 private class WrappedListIterator extends WrappedIterator implements ListIterator<V> { 837 WrappedListIterator() {} 838 839 public WrappedListIterator(int index) { 840 super(getListDelegate().listIterator(index)); 841 } 842 843 private ListIterator<V> getDelegateListIterator() { 844 return (ListIterator<V>) getDelegateIterator(); 845 } 846 847 @Override 848 public boolean hasPrevious() { 849 return getDelegateListIterator().hasPrevious(); 850 } 851 852 @Override 853 public V previous() { 854 return getDelegateListIterator().previous(); 855 } 856 857 @Override 858 public int nextIndex() { 859 return getDelegateListIterator().nextIndex(); 860 } 861 862 @Override 863 public int previousIndex() { 864 return getDelegateListIterator().previousIndex(); 865 } 866 867 @Override 868 public void set(V value) { 869 getDelegateListIterator().set(value); 870 } 871 872 @Override 873 public void add(V value) { 874 boolean wasEmpty = isEmpty(); 875 getDelegateListIterator().add(value); 876 totalSize++; 877 if (wasEmpty) { 878 addToMap(); 879 } 880 } 881 } 882 } 883 884 /** 885 * List decorator that stays in sync with the multimap values for a key and supports rapid random 886 * access. 887 */ 888 private class RandomAccessWrappedList extends WrappedList implements RandomAccess { 889 RandomAccessWrappedList( 890 @Nullable K key, List<V> delegate, @Nullable WrappedCollection ancestor) { 891 super(key, delegate, ancestor); 892 } 893 } 894 895 @Override 896 Set<K> createKeySet() { 897 return new KeySet(map); 898 } 899 900 final Set<K> createMaybeNavigableKeySet() { 901 if (map instanceof NavigableMap) { 902 return new NavigableKeySet((NavigableMap<K, Collection<V>>) map); 903 } else if (map instanceof SortedMap) { 904 return new SortedKeySet((SortedMap<K, Collection<V>>) map); 905 } else { 906 return new KeySet(map); 907 } 908 } 909 910 @WeakOuter 911 private class KeySet extends Maps.KeySet<K, Collection<V>> { 912 KeySet(final Map<K, Collection<V>> subMap) { 913 super(subMap); 914 } 915 916 @Override 917 public Iterator<K> iterator() { 918 final Iterator<Entry<K, Collection<V>>> entryIterator = map().entrySet().iterator(); 919 return new Iterator<K>() { 920 @Nullable Entry<K, Collection<V>> entry; 921 922 @Override 923 public boolean hasNext() { 924 return entryIterator.hasNext(); 925 } 926 927 @Override 928 public K next() { 929 entry = entryIterator.next(); 930 return entry.getKey(); 931 } 932 933 @Override 934 public void remove() { 935 checkRemove(entry != null); 936 Collection<V> collection = entry.getValue(); 937 entryIterator.remove(); 938 totalSize -= collection.size(); 939 collection.clear(); 940 entry = null; 941 } 942 }; 943 } 944 945 // The following methods are included for better performance. 946 947 @Override 948 public Spliterator<K> spliterator() { 949 return map().keySet().spliterator(); 950 } 951 952 @Override 953 public boolean remove(Object key) { 954 int count = 0; 955 Collection<V> collection = map().remove(key); 956 if (collection != null) { 957 count = collection.size(); 958 collection.clear(); 959 totalSize -= count; 960 } 961 return count > 0; 962 } 963 964 @Override 965 public void clear() { 966 Iterators.clear(iterator()); 967 } 968 969 @Override 970 public boolean containsAll(Collection<?> c) { 971 return map().keySet().containsAll(c); 972 } 973 974 @Override 975 public boolean equals(@Nullable Object object) { 976 return this == object || this.map().keySet().equals(object); 977 } 978 979 @Override 980 public int hashCode() { 981 return map().keySet().hashCode(); 982 } 983 } 984 985 @WeakOuter 986 private class SortedKeySet extends KeySet implements SortedSet<K> { 987 988 SortedKeySet(SortedMap<K, Collection<V>> subMap) { 989 super(subMap); 990 } 991 992 SortedMap<K, Collection<V>> sortedMap() { 993 return (SortedMap<K, Collection<V>>) super.map(); 994 } 995 996 @Override 997 public Comparator<? super K> comparator() { 998 return sortedMap().comparator(); 999 } 1000 1001 @Override 1002 public K first() { 1003 return sortedMap().firstKey(); 1004 } 1005 1006 @Override 1007 public SortedSet<K> headSet(K toElement) { 1008 return new SortedKeySet(sortedMap().headMap(toElement)); 1009 } 1010 1011 @Override 1012 public K last() { 1013 return sortedMap().lastKey(); 1014 } 1015 1016 @Override 1017 public SortedSet<K> subSet(K fromElement, K toElement) { 1018 return new SortedKeySet(sortedMap().subMap(fromElement, toElement)); 1019 } 1020 1021 @Override 1022 public SortedSet<K> tailSet(K fromElement) { 1023 return new SortedKeySet(sortedMap().tailMap(fromElement)); 1024 } 1025 } 1026 1027 @WeakOuter 1028 class NavigableKeySet extends SortedKeySet implements NavigableSet<K> { 1029 NavigableKeySet(NavigableMap<K, Collection<V>> subMap) { 1030 super(subMap); 1031 } 1032 1033 @Override 1034 NavigableMap<K, Collection<V>> sortedMap() { 1035 return (NavigableMap<K, Collection<V>>) super.sortedMap(); 1036 } 1037 1038 @Override 1039 public K lower(K k) { 1040 return sortedMap().lowerKey(k); 1041 } 1042 1043 @Override 1044 public K floor(K k) { 1045 return sortedMap().floorKey(k); 1046 } 1047 1048 @Override 1049 public K ceiling(K k) { 1050 return sortedMap().ceilingKey(k); 1051 } 1052 1053 @Override 1054 public K higher(K k) { 1055 return sortedMap().higherKey(k); 1056 } 1057 1058 @Override 1059 public K pollFirst() { 1060 return Iterators.pollNext(iterator()); 1061 } 1062 1063 @Override 1064 public K pollLast() { 1065 return Iterators.pollNext(descendingIterator()); 1066 } 1067 1068 @Override 1069 public NavigableSet<K> descendingSet() { 1070 return new NavigableKeySet(sortedMap().descendingMap()); 1071 } 1072 1073 @Override 1074 public Iterator<K> descendingIterator() { 1075 return descendingSet().iterator(); 1076 } 1077 1078 @Override 1079 public NavigableSet<K> headSet(K toElement) { 1080 return headSet(toElement, false); 1081 } 1082 1083 @Override 1084 public NavigableSet<K> headSet(K toElement, boolean inclusive) { 1085 return new NavigableKeySet(sortedMap().headMap(toElement, inclusive)); 1086 } 1087 1088 @Override 1089 public NavigableSet<K> subSet(K fromElement, K toElement) { 1090 return subSet(fromElement, true, toElement, false); 1091 } 1092 1093 @Override 1094 public NavigableSet<K> subSet( 1095 K fromElement, boolean fromInclusive, K toElement, boolean toInclusive) { 1096 return new NavigableKeySet( 1097 sortedMap().subMap(fromElement, fromInclusive, toElement, toInclusive)); 1098 } 1099 1100 @Override 1101 public NavigableSet<K> tailSet(K fromElement) { 1102 return tailSet(fromElement, true); 1103 } 1104 1105 @Override 1106 public NavigableSet<K> tailSet(K fromElement, boolean inclusive) { 1107 return new NavigableKeySet(sortedMap().tailMap(fromElement, inclusive)); 1108 } 1109 } 1110 1111 /** Removes all values for the provided key. */ 1112 private void removeValuesForKey(Object key) { 1113 Collection<V> collection = Maps.safeRemove(map, key); 1114 1115 if (collection != null) { 1116 int count = collection.size(); 1117 collection.clear(); 1118 totalSize -= count; 1119 } 1120 } 1121 1122 private abstract class Itr<T> implements Iterator<T> { 1123 final Iterator<Entry<K, Collection<V>>> keyIterator; 1124 @Nullable K key; 1125 @Nullable Collection<V> collection; 1126 Iterator<V> valueIterator; 1127 1128 Itr() { 1129 keyIterator = map.entrySet().iterator(); 1130 key = null; 1131 collection = null; 1132 valueIterator = Iterators.emptyModifiableIterator(); 1133 } 1134 1135 abstract T output(K key, V value); 1136 1137 @Override 1138 public boolean hasNext() { 1139 return keyIterator.hasNext() || valueIterator.hasNext(); 1140 } 1141 1142 @Override 1143 public T next() { 1144 if (!valueIterator.hasNext()) { 1145 Entry<K, Collection<V>> mapEntry = keyIterator.next(); 1146 key = mapEntry.getKey(); 1147 collection = mapEntry.getValue(); 1148 valueIterator = collection.iterator(); 1149 } 1150 return output(key, valueIterator.next()); 1151 } 1152 1153 @Override 1154 public void remove() { 1155 valueIterator.remove(); 1156 if (collection.isEmpty()) { 1157 keyIterator.remove(); 1158 } 1159 totalSize--; 1160 } 1161 } 1162 1163 /** 1164 * {@inheritDoc} 1165 * 1166 * <p>The iterator generated by the returned collection traverses the values for one key, followed 1167 * by the values of a second key, and so on. 1168 */ 1169 @Override 1170 public Collection<V> values() { 1171 return super.values(); 1172 } 1173 1174 @Override 1175 Collection<V> createValues() { 1176 return new Values(); 1177 } 1178 1179 @Override 1180 Iterator<V> valueIterator() { 1181 return new Itr<V>() { 1182 @Override 1183 V output(K key, V value) { 1184 return value; 1185 } 1186 }; 1187 } 1188 1189 @Override 1190 Spliterator<V> valueSpliterator() { 1191 return CollectSpliterators.flatMap( 1192 map.values().spliterator(), Collection::spliterator, Spliterator.SIZED, size()); 1193 } 1194 1195 /* 1196 * TODO(kevinb): should we copy this javadoc to each concrete class, so that 1197 * classes like LinkedHashMultimap that need to say something different are 1198 * still able to {@inheritDoc} all the way from Multimap? 1199 */ 1200 1201 @Override 1202 Multiset<K> createKeys() { 1203 return new Multimaps.Keys<K, V>(this); 1204 } 1205 1206 /** 1207 * {@inheritDoc} 1208 * 1209 * <p>The iterator generated by the returned collection traverses the values for one key, followed 1210 * by the values of a second key, and so on. 1211 * 1212 * <p>Each entry is an immutable snapshot of a key-value mapping in the multimap, taken at the 1213 * time the entry is returned by a method call to the collection or its iterator. 1214 */ 1215 @Override 1216 public Collection<Entry<K, V>> entries() { 1217 return super.entries(); 1218 } 1219 1220 @Override 1221 Collection<Entry<K, V>> createEntries() { 1222 if (this instanceof SetMultimap) { 1223 return new EntrySet(); 1224 } else { 1225 return new Entries(); 1226 } 1227 } 1228 1229 /** 1230 * Returns an iterator across all key-value map entries, used by {@code entries().iterator()} and 1231 * {@code values().iterator()}. The default behavior, which traverses the values for one key, the 1232 * values for a second key, and so on, suffices for most {@code AbstractMapBasedMultimap} 1233 * implementations. 1234 * 1235 * @return an iterator across map entries 1236 */ 1237 @Override 1238 Iterator<Entry<K, V>> entryIterator() { 1239 return new Itr<Entry<K, V>>() { 1240 @Override 1241 Entry<K, V> output(K key, V value) { 1242 return Maps.immutableEntry(key, value); 1243 } 1244 }; 1245 } 1246 1247 @Override 1248 Spliterator<Entry<K, V>> entrySpliterator() { 1249 return CollectSpliterators.flatMap( 1250 map.entrySet().spliterator(), 1251 keyToValueCollectionEntry -> { 1252 K key = keyToValueCollectionEntry.getKey(); 1253 Collection<V> valueCollection = keyToValueCollectionEntry.getValue(); 1254 return CollectSpliterators.map( 1255 valueCollection.spliterator(), (V value) -> Maps.immutableEntry(key, value)); 1256 }, 1257 Spliterator.SIZED, 1258 size()); 1259 } 1260 1261 @Override 1262 public void forEach(BiConsumer<? super K, ? super V> action) { 1263 checkNotNull(action); 1264 map.forEach( 1265 (key, valueCollection) -> valueCollection.forEach(value -> action.accept(key, value))); 1266 } 1267 1268 @Override 1269 Map<K, Collection<V>> createAsMap() { 1270 return new AsMap(map); 1271 } 1272 1273 final Map<K, Collection<V>> createMaybeNavigableAsMap() { 1274 if (map instanceof NavigableMap) { 1275 return new NavigableAsMap((NavigableMap<K, Collection<V>>) map); 1276 } else if (map instanceof SortedMap) { 1277 return new SortedAsMap((SortedMap<K, Collection<V>>) map); 1278 } else { 1279 return new AsMap(map); 1280 } 1281 } 1282 1283 @WeakOuter 1284 private class AsMap extends ViewCachingAbstractMap<K, Collection<V>> { 1285 /** 1286 * Usually the same as map, but smaller for the headMap(), tailMap(), or subMap() of a 1287 * SortedAsMap. 1288 */ 1289 final transient Map<K, Collection<V>> submap; 1290 1291 AsMap(Map<K, Collection<V>> submap) { 1292 this.submap = submap; 1293 } 1294 1295 @Override 1296 protected Set<Entry<K, Collection<V>>> createEntrySet() { 1297 return new AsMapEntries(); 1298 } 1299 1300 // The following methods are included for performance. 1301 1302 @Override 1303 public boolean containsKey(Object key) { 1304 return Maps.safeContainsKey(submap, key); 1305 } 1306 1307 @Override 1308 public Collection<V> get(Object key) { 1309 Collection<V> collection = Maps.safeGet(submap, key); 1310 if (collection == null) { 1311 return null; 1312 } 1313 @SuppressWarnings("unchecked") 1314 K k = (K) key; 1315 return wrapCollection(k, collection); 1316 } 1317 1318 @Override 1319 public Set<K> keySet() { 1320 return AbstractMapBasedMultimap.this.keySet(); 1321 } 1322 1323 @Override 1324 public int size() { 1325 return submap.size(); 1326 } 1327 1328 @Override 1329 public Collection<V> remove(Object key) { 1330 Collection<V> collection = submap.remove(key); 1331 if (collection == null) { 1332 return null; 1333 } 1334 1335 Collection<V> output = createCollection(); 1336 output.addAll(collection); 1337 totalSize -= collection.size(); 1338 collection.clear(); 1339 return output; 1340 } 1341 1342 @Override 1343 public boolean equals(@Nullable Object object) { 1344 return this == object || submap.equals(object); 1345 } 1346 1347 @Override 1348 public int hashCode() { 1349 return submap.hashCode(); 1350 } 1351 1352 @Override 1353 public String toString() { 1354 return submap.toString(); 1355 } 1356 1357 @Override 1358 public void clear() { 1359 if (submap == map) { 1360 AbstractMapBasedMultimap.this.clear(); 1361 } else { 1362 Iterators.clear(new AsMapIterator()); 1363 } 1364 } 1365 1366 Entry<K, Collection<V>> wrapEntry(Entry<K, Collection<V>> entry) { 1367 K key = entry.getKey(); 1368 return Maps.immutableEntry(key, wrapCollection(key, entry.getValue())); 1369 } 1370 1371 @WeakOuter 1372 class AsMapEntries extends Maps.EntrySet<K, Collection<V>> { 1373 @Override 1374 Map<K, Collection<V>> map() { 1375 return AsMap.this; 1376 } 1377 1378 @Override 1379 public Iterator<Entry<K, Collection<V>>> iterator() { 1380 return new AsMapIterator(); 1381 } 1382 1383 @Override 1384 public Spliterator<Entry<K, Collection<V>>> spliterator() { 1385 return CollectSpliterators.map(submap.entrySet().spliterator(), AsMap.this::wrapEntry); 1386 } 1387 1388 // The following methods are included for performance. 1389 1390 @Override 1391 public boolean contains(Object o) { 1392 return Collections2.safeContains(submap.entrySet(), o); 1393 } 1394 1395 @Override 1396 public boolean remove(Object o) { 1397 if (!contains(o)) { 1398 return false; 1399 } 1400 Entry<?, ?> entry = (Entry<?, ?>) o; 1401 removeValuesForKey(entry.getKey()); 1402 return true; 1403 } 1404 } 1405 1406 /** Iterator across all keys and value collections. */ 1407 class AsMapIterator implements Iterator<Entry<K, Collection<V>>> { 1408 final Iterator<Entry<K, Collection<V>>> delegateIterator = submap.entrySet().iterator(); 1409 @Nullable Collection<V> collection; 1410 1411 @Override 1412 public boolean hasNext() { 1413 return delegateIterator.hasNext(); 1414 } 1415 1416 @Override 1417 public Entry<K, Collection<V>> next() { 1418 Entry<K, Collection<V>> entry = delegateIterator.next(); 1419 collection = entry.getValue(); 1420 return wrapEntry(entry); 1421 } 1422 1423 @Override 1424 public void remove() { 1425 checkRemove(collection != null); 1426 delegateIterator.remove(); 1427 totalSize -= collection.size(); 1428 collection.clear(); 1429 collection = null; 1430 } 1431 } 1432 } 1433 1434 @WeakOuter 1435 private class SortedAsMap extends AsMap implements SortedMap<K, Collection<V>> { 1436 SortedAsMap(SortedMap<K, Collection<V>> submap) { 1437 super(submap); 1438 } 1439 1440 SortedMap<K, Collection<V>> sortedMap() { 1441 return (SortedMap<K, Collection<V>>) submap; 1442 } 1443 1444 @Override 1445 public Comparator<? super K> comparator() { 1446 return sortedMap().comparator(); 1447 } 1448 1449 @Override 1450 public K firstKey() { 1451 return sortedMap().firstKey(); 1452 } 1453 1454 @Override 1455 public K lastKey() { 1456 return sortedMap().lastKey(); 1457 } 1458 1459 @Override 1460 public SortedMap<K, Collection<V>> headMap(K toKey) { 1461 return new SortedAsMap(sortedMap().headMap(toKey)); 1462 } 1463 1464 @Override 1465 public SortedMap<K, Collection<V>> subMap(K fromKey, K toKey) { 1466 return new SortedAsMap(sortedMap().subMap(fromKey, toKey)); 1467 } 1468 1469 @Override 1470 public SortedMap<K, Collection<V>> tailMap(K fromKey) { 1471 return new SortedAsMap(sortedMap().tailMap(fromKey)); 1472 } 1473 1474 @Nullable SortedSet<K> sortedKeySet; 1475 1476 // returns a SortedSet, even though returning a Set would be sufficient to 1477 // satisfy the SortedMap.keySet() interface 1478 @Override 1479 public SortedSet<K> keySet() { 1480 SortedSet<K> result = sortedKeySet; 1481 return (result == null) ? sortedKeySet = createKeySet() : result; 1482 } 1483 1484 @Override 1485 SortedSet<K> createKeySet() { 1486 return new SortedKeySet(sortedMap()); 1487 } 1488 } 1489 1490 class NavigableAsMap extends SortedAsMap implements NavigableMap<K, Collection<V>> { 1491 1492 NavigableAsMap(NavigableMap<K, Collection<V>> submap) { 1493 super(submap); 1494 } 1495 1496 @Override 1497 NavigableMap<K, Collection<V>> sortedMap() { 1498 return (NavigableMap<K, Collection<V>>) super.sortedMap(); 1499 } 1500 1501 @Override 1502 public Entry<K, Collection<V>> lowerEntry(K key) { 1503 Entry<K, Collection<V>> entry = sortedMap().lowerEntry(key); 1504 return (entry == null) ? null : wrapEntry(entry); 1505 } 1506 1507 @Override 1508 public K lowerKey(K key) { 1509 return sortedMap().lowerKey(key); 1510 } 1511 1512 @Override 1513 public Entry<K, Collection<V>> floorEntry(K key) { 1514 Entry<K, Collection<V>> entry = sortedMap().floorEntry(key); 1515 return (entry == null) ? null : wrapEntry(entry); 1516 } 1517 1518 @Override 1519 public K floorKey(K key) { 1520 return sortedMap().floorKey(key); 1521 } 1522 1523 @Override 1524 public Entry<K, Collection<V>> ceilingEntry(K key) { 1525 Entry<K, Collection<V>> entry = sortedMap().ceilingEntry(key); 1526 return (entry == null) ? null : wrapEntry(entry); 1527 } 1528 1529 @Override 1530 public K ceilingKey(K key) { 1531 return sortedMap().ceilingKey(key); 1532 } 1533 1534 @Override 1535 public Entry<K, Collection<V>> higherEntry(K key) { 1536 Entry<K, Collection<V>> entry = sortedMap().higherEntry(key); 1537 return (entry == null) ? null : wrapEntry(entry); 1538 } 1539 1540 @Override 1541 public K higherKey(K key) { 1542 return sortedMap().higherKey(key); 1543 } 1544 1545 @Override 1546 public Entry<K, Collection<V>> firstEntry() { 1547 Entry<K, Collection<V>> entry = sortedMap().firstEntry(); 1548 return (entry == null) ? null : wrapEntry(entry); 1549 } 1550 1551 @Override 1552 public Entry<K, Collection<V>> lastEntry() { 1553 Entry<K, Collection<V>> entry = sortedMap().lastEntry(); 1554 return (entry == null) ? null : wrapEntry(entry); 1555 } 1556 1557 @Override 1558 public Entry<K, Collection<V>> pollFirstEntry() { 1559 return pollAsMapEntry(entrySet().iterator()); 1560 } 1561 1562 @Override 1563 public Entry<K, Collection<V>> pollLastEntry() { 1564 return pollAsMapEntry(descendingMap().entrySet().iterator()); 1565 } 1566 1567 Entry<K, Collection<V>> pollAsMapEntry(Iterator<Entry<K, Collection<V>>> entryIterator) { 1568 if (!entryIterator.hasNext()) { 1569 return null; 1570 } 1571 Entry<K, Collection<V>> entry = entryIterator.next(); 1572 Collection<V> output = createCollection(); 1573 output.addAll(entry.getValue()); 1574 entryIterator.remove(); 1575 return Maps.immutableEntry(entry.getKey(), unmodifiableCollectionSubclass(output)); 1576 } 1577 1578 @Override 1579 public NavigableMap<K, Collection<V>> descendingMap() { 1580 return new NavigableAsMap(sortedMap().descendingMap()); 1581 } 1582 1583 @Override 1584 public NavigableSet<K> keySet() { 1585 return (NavigableSet<K>) super.keySet(); 1586 } 1587 1588 @Override 1589 NavigableSet<K> createKeySet() { 1590 return new NavigableKeySet(sortedMap()); 1591 } 1592 1593 @Override 1594 public NavigableSet<K> navigableKeySet() { 1595 return keySet(); 1596 } 1597 1598 @Override 1599 public NavigableSet<K> descendingKeySet() { 1600 return descendingMap().navigableKeySet(); 1601 } 1602 1603 @Override 1604 public NavigableMap<K, Collection<V>> subMap(K fromKey, K toKey) { 1605 return subMap(fromKey, true, toKey, false); 1606 } 1607 1608 @Override 1609 public NavigableMap<K, Collection<V>> subMap( 1610 K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { 1611 return new NavigableAsMap(sortedMap().subMap(fromKey, fromInclusive, toKey, toInclusive)); 1612 } 1613 1614 @Override 1615 public NavigableMap<K, Collection<V>> headMap(K toKey) { 1616 return headMap(toKey, false); 1617 } 1618 1619 @Override 1620 public NavigableMap<K, Collection<V>> headMap(K toKey, boolean inclusive) { 1621 return new NavigableAsMap(sortedMap().headMap(toKey, inclusive)); 1622 } 1623 1624 @Override 1625 public NavigableMap<K, Collection<V>> tailMap(K fromKey) { 1626 return tailMap(fromKey, true); 1627 } 1628 1629 @Override 1630 public NavigableMap<K, Collection<V>> tailMap(K fromKey, boolean inclusive) { 1631 return new NavigableAsMap(sortedMap().tailMap(fromKey, inclusive)); 1632 } 1633 } 1634 1635 private static final long serialVersionUID = 2447537837011683357L; 1636 }