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