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