001    /*
002     * Copyright (C) 2007 The Guava Authors
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package com.google.common.collect;
018    
019    import static com.google.common.base.Preconditions.checkArgument;
020    import static com.google.common.base.Preconditions.checkNotNull;
021    import static com.google.common.base.Preconditions.checkState;
022    
023    import com.google.common.annotations.Beta;
024    import com.google.common.annotations.GwtCompatible;
025    import com.google.common.annotations.GwtIncompatible;
026    import com.google.common.base.Function;
027    import com.google.common.base.Joiner;
028    import com.google.common.base.Joiner.MapJoiner;
029    import com.google.common.base.Objects;
030    import com.google.common.base.Predicate;
031    import com.google.common.base.Predicates;
032    import com.google.common.base.Supplier;
033    import com.google.common.collect.Collections2.TransformedCollection;
034    import com.google.common.collect.Maps.EntryTransformer;
035    
036    import java.io.IOException;
037    import java.io.ObjectInputStream;
038    import java.io.ObjectOutputStream;
039    import java.io.Serializable;
040    import java.util.AbstractCollection;
041    import java.util.AbstractSet;
042    import java.util.Collection;
043    import java.util.Collections;
044    import java.util.Comparator;
045    import java.util.HashSet;
046    import java.util.Iterator;
047    import java.util.List;
048    import java.util.Map;
049    import java.util.Map.Entry;
050    import java.util.NoSuchElementException;
051    import java.util.Set;
052    import java.util.SortedSet;
053    
054    import javax.annotation.Nullable;
055    
056    /**
057     * Provides static methods acting on or generating a {@code Multimap}.
058     *
059     * @author Jared Levy
060     * @author Robert Konigsberg
061     * @author Mike Bostock
062     * @author Louis Wasserman
063     * @since 2.0 (imported from Google Collections Library)
064     */
065    @GwtCompatible(emulated = true)
066    public final class Multimaps {
067      private Multimaps() {}
068    
069      /**
070       * Creates a new {@code Multimap} that uses the provided map and factory. It
071       * can generate a multimap based on arbitrary {@link Map} and
072       * {@link Collection} classes.
073       *
074       * <p>The {@code factory}-generated and {@code map} classes determine the
075       * multimap iteration order. They also specify the behavior of the
076       * {@code equals}, {@code hashCode}, and {@code toString} methods for the
077       * multimap and its returned views. However, the multimap's {@code get}
078       * method returns instances of a different class than {@code factory.get()}
079       * does.
080       *
081       * <p>The multimap is serializable if {@code map}, {@code factory}, the
082       * collections generated by {@code factory}, and the multimap contents are all
083       * serializable.
084       *
085       * <p>The multimap is not threadsafe when any concurrent operations update the
086       * multimap, even if {@code map} and the instances generated by
087       * {@code factory} are. Concurrent read operations will work correctly. To
088       * allow concurrent update operations, wrap the multimap with a call to
089       * {@link #synchronizedMultimap}.
090       *
091       * <p>Call this method only when the simpler methods
092       * {@link ArrayListMultimap#create()}, {@link HashMultimap#create()},
093       * {@link LinkedHashMultimap#create()}, {@link LinkedListMultimap#create()},
094       * {@link TreeMultimap#create()}, and
095       * {@link TreeMultimap#create(Comparator, Comparator)} won't suffice.
096       *
097       * <p>Note: the multimap assumes complete ownership over of {@code map} and
098       * the collections returned by {@code factory}. Those objects should not be
099       * manually updated and they should not use soft, weak, or phantom references.
100       *
101       * @param map place to store the mapping from each key to its corresponding
102       *     values
103       * @param factory supplier of new, empty collections that will each hold all
104       *     values for a given key
105       * @throws IllegalArgumentException if {@code map} is not empty
106       */
107      public static <K, V> Multimap<K, V> newMultimap(Map<K, Collection<V>> map,
108          final Supplier<? extends Collection<V>> factory) {
109        return new CustomMultimap<K, V>(map, factory);
110      }
111    
112      private static class CustomMultimap<K, V> extends AbstractMultimap<K, V> {
113        transient Supplier<? extends Collection<V>> factory;
114    
115        CustomMultimap(Map<K, Collection<V>> map,
116            Supplier<? extends Collection<V>> factory) {
117          super(map);
118          this.factory = checkNotNull(factory);
119        }
120    
121        @Override protected Collection<V> createCollection() {
122          return factory.get();
123        }
124    
125        // can't use Serialization writeMultimap and populateMultimap methods since
126        // there's no way to generate the empty backing map.
127    
128        /** @serialData the factory and the backing map */
129        @GwtIncompatible("java.io.ObjectOutputStream")
130        private void writeObject(ObjectOutputStream stream) throws IOException {
131          stream.defaultWriteObject();
132          stream.writeObject(factory);
133          stream.writeObject(backingMap());
134        }
135    
136        @GwtIncompatible("java.io.ObjectInputStream")
137        @SuppressWarnings("unchecked") // reading data stored by writeObject
138        private void readObject(ObjectInputStream stream)
139            throws IOException, ClassNotFoundException {
140          stream.defaultReadObject();
141          factory = (Supplier<? extends Collection<V>>) stream.readObject();
142          Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject();
143          setMap(map);
144        }
145    
146        @GwtIncompatible("java serialization not supported")
147        private static final long serialVersionUID = 0;
148      }
149    
150      /**
151       * Creates a new {@code ListMultimap} that uses the provided map and factory.
152       * It can generate a multimap based on arbitrary {@link Map} and {@link List}
153       * classes.
154       *
155       * <p>The {@code factory}-generated and {@code map} classes determine the
156       * multimap iteration order. They also specify the behavior of the
157       * {@code equals}, {@code hashCode}, and {@code toString} methods for the
158       * multimap and its returned views. The multimap's {@code get}, {@code
159       * removeAll}, and {@code replaceValues} methods return {@code RandomAccess}
160       * lists if the factory does. However, the multimap's {@code get} method
161       * returns instances of a different class than does {@code factory.get()}.
162       *
163       * <p>The multimap is serializable if {@code map}, {@code factory}, the
164       * lists generated by {@code factory}, and the multimap contents are all
165       * serializable.
166       *
167       * <p>The multimap is not threadsafe when any concurrent operations update the
168       * multimap, even if {@code map} and the instances generated by
169       * {@code factory} are. Concurrent read operations will work correctly. To
170       * allow concurrent update operations, wrap the multimap with a call to
171       * {@link #synchronizedListMultimap}.
172       *
173       * <p>Call this method only when the simpler methods
174       * {@link ArrayListMultimap#create()} and {@link LinkedListMultimap#create()}
175       * won't suffice.
176       *
177       * <p>Note: the multimap assumes complete ownership over of {@code map} and
178       * the lists returned by {@code factory}. Those objects should not be manually
179       * updated, they should be empty when provided, and they should not use soft,
180       * weak, or phantom references.
181       *
182       * @param map place to store the mapping from each key to its corresponding
183       *     values
184       * @param factory supplier of new, empty lists that will each hold all values
185       *     for a given key
186       * @throws IllegalArgumentException if {@code map} is not empty
187       */
188      public static <K, V> ListMultimap<K, V> newListMultimap(
189          Map<K, Collection<V>> map, final Supplier<? extends List<V>> factory) {
190        return new CustomListMultimap<K, V>(map, factory);
191      }
192    
193      private static class CustomListMultimap<K, V>
194          extends AbstractListMultimap<K, V> {
195        transient Supplier<? extends List<V>> factory;
196    
197        CustomListMultimap(Map<K, Collection<V>> map,
198            Supplier<? extends List<V>> factory) {
199          super(map);
200          this.factory = checkNotNull(factory);
201        }
202    
203        @Override protected List<V> createCollection() {
204          return factory.get();
205        }
206    
207        /** @serialData the factory and the backing map */
208        @GwtIncompatible("java.io.ObjectOutputStream")
209        private void writeObject(ObjectOutputStream stream) throws IOException {
210          stream.defaultWriteObject();
211          stream.writeObject(factory);
212          stream.writeObject(backingMap());
213        }
214    
215        @GwtIncompatible("java.io.ObjectInputStream")
216        @SuppressWarnings("unchecked") // reading data stored by writeObject
217        private void readObject(ObjectInputStream stream)
218            throws IOException, ClassNotFoundException {
219          stream.defaultReadObject();
220          factory = (Supplier<? extends List<V>>) stream.readObject();
221          Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject();
222          setMap(map);
223        }
224    
225        @GwtIncompatible("java serialization not supported")
226        private static final long serialVersionUID = 0;
227      }
228    
229      /**
230       * Creates a new {@code SetMultimap} that uses the provided map and factory.
231       * It can generate a multimap based on arbitrary {@link Map} and {@link Set}
232       * classes.
233       *
234       * <p>The {@code factory}-generated and {@code map} classes determine the
235       * multimap iteration order. They also specify the behavior of the
236       * {@code equals}, {@code hashCode}, and {@code toString} methods for the
237       * multimap and its returned views. However, the multimap's {@code get}
238       * method returns instances of a different class than {@code factory.get()}
239       * does.
240       *
241       * <p>The multimap is serializable if {@code map}, {@code factory}, the
242       * sets generated by {@code factory}, and the multimap contents are all
243       * serializable.
244       *
245       * <p>The multimap is not threadsafe when any concurrent operations update the
246       * multimap, even if {@code map} and the instances generated by
247       * {@code factory} are. Concurrent read operations will work correctly. To
248       * allow concurrent update operations, wrap the multimap with a call to
249       * {@link #synchronizedSetMultimap}.
250       *
251       * <p>Call this method only when the simpler methods
252       * {@link HashMultimap#create()}, {@link LinkedHashMultimap#create()},
253       * {@link TreeMultimap#create()}, and
254       * {@link TreeMultimap#create(Comparator, Comparator)} won't suffice.
255       *
256       * <p>Note: the multimap assumes complete ownership over of {@code map} and
257       * the sets returned by {@code factory}. Those objects should not be manually
258       * updated and they should not use soft, weak, or phantom references.
259       *
260       * @param map place to store the mapping from each key to its corresponding
261       *     values
262       * @param factory supplier of new, empty sets that will each hold all values
263       *     for a given key
264       * @throws IllegalArgumentException if {@code map} is not empty
265       */
266      public static <K, V> SetMultimap<K, V> newSetMultimap(
267          Map<K, Collection<V>> map, final Supplier<? extends Set<V>> factory) {
268        return new CustomSetMultimap<K, V>(map, factory);
269      }
270    
271      private static class CustomSetMultimap<K, V>
272          extends AbstractSetMultimap<K, V> {
273        transient Supplier<? extends Set<V>> factory;
274    
275        CustomSetMultimap(Map<K, Collection<V>> map,
276            Supplier<? extends Set<V>> factory) {
277          super(map);
278          this.factory = checkNotNull(factory);
279        }
280    
281        @Override protected Set<V> createCollection() {
282          return factory.get();
283        }
284    
285        /** @serialData the factory and the backing map */
286        @GwtIncompatible("java.io.ObjectOutputStream")
287        private void writeObject(ObjectOutputStream stream) throws IOException {
288          stream.defaultWriteObject();
289          stream.writeObject(factory);
290          stream.writeObject(backingMap());
291        }
292    
293        @GwtIncompatible("java.io.ObjectInputStream")
294        @SuppressWarnings("unchecked") // reading data stored by writeObject
295        private void readObject(ObjectInputStream stream)
296            throws IOException, ClassNotFoundException {
297          stream.defaultReadObject();
298          factory = (Supplier<? extends Set<V>>) stream.readObject();
299          Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject();
300          setMap(map);
301        }
302    
303        @GwtIncompatible("not needed in emulated source")
304        private static final long serialVersionUID = 0;
305      }
306    
307      /**
308       * Creates a new {@code SortedSetMultimap} that uses the provided map and
309       * factory. It can generate a multimap based on arbitrary {@link Map} and
310       * {@link SortedSet} classes.
311       *
312       * <p>The {@code factory}-generated and {@code map} classes determine the
313       * multimap iteration order. They also specify the behavior of the
314       * {@code equals}, {@code hashCode}, and {@code toString} methods for the
315       * multimap and its returned views. However, the multimap's {@code get}
316       * method returns instances of a different class than {@code factory.get()}
317       * does.
318       *
319       * <p>The multimap is serializable if {@code map}, {@code factory}, the
320       * sets generated by {@code factory}, and the multimap contents are all
321       * serializable.
322       *
323       * <p>The multimap is not threadsafe when any concurrent operations update the
324       * multimap, even if {@code map} and the instances generated by
325       * {@code factory} are. Concurrent read operations will work correctly. To
326       * allow concurrent update operations, wrap the multimap with a call to
327       * {@link #synchronizedSortedSetMultimap}.
328       *
329       * <p>Call this method only when the simpler methods
330       * {@link TreeMultimap#create()} and
331       * {@link TreeMultimap#create(Comparator, Comparator)} won't suffice.
332       *
333       * <p>Note: the multimap assumes complete ownership over of {@code map} and
334       * the sets returned by {@code factory}. Those objects should not be manually
335       * updated and they should not use soft, weak, or phantom references.
336       *
337       * @param map place to store the mapping from each key to its corresponding
338       *     values
339       * @param factory supplier of new, empty sorted sets that will each hold
340       *     all values for a given key
341       * @throws IllegalArgumentException if {@code map} is not empty
342       */
343      public static <K, V> SortedSetMultimap<K, V> newSortedSetMultimap(
344          Map<K, Collection<V>> map,
345          final Supplier<? extends SortedSet<V>> factory) {
346        return new CustomSortedSetMultimap<K, V>(map, factory);
347      }
348    
349      private static class CustomSortedSetMultimap<K, V>
350          extends AbstractSortedSetMultimap<K, V> {
351        transient Supplier<? extends SortedSet<V>> factory;
352        transient Comparator<? super V> valueComparator;
353    
354        CustomSortedSetMultimap(Map<K, Collection<V>> map,
355            Supplier<? extends SortedSet<V>> factory) {
356          super(map);
357          this.factory = checkNotNull(factory);
358          valueComparator = factory.get().comparator();
359        }
360    
361        @Override protected SortedSet<V> createCollection() {
362          return factory.get();
363        }
364    
365        @Override public Comparator<? super V> valueComparator() {
366          return valueComparator;
367        }
368    
369        /** @serialData the factory and the backing map */
370        @GwtIncompatible("java.io.ObjectOutputStream")
371        private void writeObject(ObjectOutputStream stream) throws IOException {
372          stream.defaultWriteObject();
373          stream.writeObject(factory);
374          stream.writeObject(backingMap());
375        }
376    
377        @GwtIncompatible("java.io.ObjectInputStream")
378        @SuppressWarnings("unchecked") // reading data stored by writeObject
379        private void readObject(ObjectInputStream stream)
380            throws IOException, ClassNotFoundException {
381          stream.defaultReadObject();
382          factory = (Supplier<? extends SortedSet<V>>) stream.readObject();
383          valueComparator = factory.get().comparator();
384          Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject();
385          setMap(map);
386        }
387    
388        @GwtIncompatible("not needed in emulated source")
389        private static final long serialVersionUID = 0;
390      }
391    
392      /**
393       * Copies each key-value mapping in {@code source} into {@code dest}, with
394       * its key and value reversed.
395       *
396       * <p>If {@code source} is an {@link ImmutableMultimap}, consider using
397       * {@link ImmutableMultimap#inverse} instead.
398       *
399       * @param source any multimap
400       * @param dest the multimap to copy into; usually empty
401       * @return {@code dest}
402       */
403      public static <K, V, M extends Multimap<K, V>> M invertFrom(
404          Multimap<? extends V, ? extends K> source, M dest) {
405        checkNotNull(dest);
406        for (Map.Entry<? extends V, ? extends K> entry : source.entries()) {
407          dest.put(entry.getValue(), entry.getKey());
408        }
409        return dest;
410      }
411    
412      /**
413       * Returns a synchronized (thread-safe) multimap backed by the specified
414       * multimap. In order to guarantee serial access, it is critical that
415       * <b>all</b> access to the backing multimap is accomplished through the
416       * returned multimap.
417       *
418       * <p>It is imperative that the user manually synchronize on the returned
419       * multimap when accessing any of its collection views: <pre>   {@code
420       *
421       *   Multimap<K, V> m = Multimaps.synchronizedMultimap(
422       *       HashMultimap.<K, V>create());
423       *   ...
424       *   Set<K> s = m.keySet();  // Needn't be in synchronized block
425       *   ...
426       *   synchronized (m) {  // Synchronizing on m, not s!
427       *     Iterator<K> i = s.iterator(); // Must be in synchronized block
428       *     while (i.hasNext()) {
429       *       foo(i.next());
430       *     }
431       *   }}</pre>
432       *
433       * Failure to follow this advice may result in non-deterministic behavior.
434       *
435       * <p>Note that the generated multimap's {@link Multimap#removeAll} and
436       * {@link Multimap#replaceValues} methods return collections that aren't
437       * synchronized.
438       *
439       * <p>The returned multimap will be serializable if the specified multimap is
440       * serializable.
441       *
442       * @param multimap the multimap to be wrapped in a synchronized view
443       * @return a synchronized view of the specified multimap
444       */
445      public static <K, V> Multimap<K, V> synchronizedMultimap(
446          Multimap<K, V> multimap) {
447        return Synchronized.multimap(multimap, null);
448      }
449    
450      /**
451       * Returns an unmodifiable view of the specified multimap. Query operations on
452       * the returned multimap "read through" to the specified multimap, and
453       * attempts to modify the returned multimap, either directly or through the
454       * multimap's views, result in an {@code UnsupportedOperationException}.
455       *
456       * <p>Note that the generated multimap's {@link Multimap#removeAll} and
457       * {@link Multimap#replaceValues} methods return collections that are
458       * modifiable.
459       *
460       * <p>The returned multimap will be serializable if the specified multimap is
461       * serializable.
462       *
463       * @param delegate the multimap for which an unmodifiable view is to be
464       *     returned
465       * @return an unmodifiable view of the specified multimap
466       */
467      public static <K, V> Multimap<K, V> unmodifiableMultimap(
468          Multimap<K, V> delegate) {
469        if (delegate instanceof UnmodifiableMultimap ||
470            delegate instanceof ImmutableMultimap) {
471          return delegate;
472        }
473        return new UnmodifiableMultimap<K, V>(delegate);
474      }
475    
476      /**
477       * Simply returns its argument.
478       *
479       * @deprecated no need to use this
480       * @since 10.0
481       */
482      @Deprecated public static <K, V> Multimap<K, V> unmodifiableMultimap(
483          ImmutableMultimap<K, V> delegate) {
484        return checkNotNull(delegate);
485      }
486    
487      private static class UnmodifiableMultimap<K, V>
488          extends ForwardingMultimap<K, V> implements Serializable {
489        final Multimap<K, V> delegate;
490        transient Collection<Entry<K, V>> entries;
491        transient Multiset<K> keys;
492        transient Set<K> keySet;
493        transient Collection<V> values;
494        transient Map<K, Collection<V>> map;
495    
496        UnmodifiableMultimap(final Multimap<K, V> delegate) {
497          this.delegate = checkNotNull(delegate);
498        }
499    
500        @Override protected Multimap<K, V> delegate() {
501          return delegate;
502        }
503    
504        @Override public void clear() {
505          throw new UnsupportedOperationException();
506        }
507    
508        @Override public Map<K, Collection<V>> asMap() {
509          Map<K, Collection<V>> result = map;
510          if (result == null) {
511            final Map<K, Collection<V>> unmodifiableMap
512                = Collections.unmodifiableMap(delegate.asMap());
513            map = result = new ForwardingMap<K, Collection<V>>() {
514              @Override protected Map<K, Collection<V>> delegate() {
515                return unmodifiableMap;
516              }
517    
518              Set<Entry<K, Collection<V>>> entrySet;
519    
520              @Override public Set<Map.Entry<K, Collection<V>>> entrySet() {
521                Set<Entry<K, Collection<V>>> result = entrySet;
522                return (result == null)
523                    ? entrySet
524                        = unmodifiableAsMapEntries(unmodifiableMap.entrySet())
525                    : result;
526              }
527    
528              @Override public Collection<V> get(Object key) {
529                Collection<V> collection = unmodifiableMap.get(key);
530                return (collection == null)
531                    ? null : unmodifiableValueCollection(collection);
532              }
533    
534              Collection<Collection<V>> asMapValues;
535    
536              @Override public Collection<Collection<V>> values() {
537                Collection<Collection<V>> result = asMapValues;
538                return (result == null)
539                    ? asMapValues
540                        = new UnmodifiableAsMapValues<V>(unmodifiableMap.values())
541                    : result;
542              }
543    
544              @Override public boolean containsValue(Object o) {
545                return values().contains(o);
546              }
547            };
548          }
549          return result;
550        }
551    
552        @Override public Collection<Entry<K, V>> entries() {
553          Collection<Entry<K, V>> result = entries;
554          if (result == null) {
555            entries = result = unmodifiableEntries(delegate.entries());
556          }
557          return result;
558        }
559    
560        @Override public Collection<V> get(K key) {
561          return unmodifiableValueCollection(delegate.get(key));
562        }
563    
564        @Override public Multiset<K> keys() {
565          Multiset<K> result = keys;
566          if (result == null) {
567            keys = result = Multisets.unmodifiableMultiset(delegate.keys());
568          }
569          return result;
570        }
571    
572        @Override public Set<K> keySet() {
573          Set<K> result = keySet;
574          if (result == null) {
575            keySet = result = Collections.unmodifiableSet(delegate.keySet());
576          }
577          return result;
578        }
579    
580        @Override public boolean put(K key, V value) {
581          throw new UnsupportedOperationException();
582        }
583    
584        @Override public boolean putAll(K key, Iterable<? extends V> values) {
585          throw new UnsupportedOperationException();
586        }
587    
588        @Override
589        public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
590          throw new UnsupportedOperationException();
591        }
592    
593        @Override public boolean remove(Object key, Object value) {
594          throw new UnsupportedOperationException();
595        }
596    
597        @Override public Collection<V> removeAll(Object key) {
598          throw new UnsupportedOperationException();
599        }
600    
601        @Override public Collection<V> replaceValues(
602            K key, Iterable<? extends V> values) {
603          throw new UnsupportedOperationException();
604        }
605    
606        @Override public Collection<V> values() {
607          Collection<V> result = values;
608          if (result == null) {
609            values = result = Collections.unmodifiableCollection(delegate.values());
610          }
611          return result;
612        }
613    
614        private static final long serialVersionUID = 0;
615      }
616    
617      private static class UnmodifiableAsMapValues<V>
618          extends ForwardingCollection<Collection<V>> {
619        final Collection<Collection<V>> delegate;
620        UnmodifiableAsMapValues(Collection<Collection<V>> delegate) {
621          this.delegate = Collections.unmodifiableCollection(delegate);
622        }
623        @Override protected Collection<Collection<V>> delegate() {
624          return delegate;
625        }
626        @Override public Iterator<Collection<V>> iterator() {
627          final Iterator<Collection<V>> iterator = delegate.iterator();
628          return new Iterator<Collection<V>>() {
629            @Override
630            public boolean hasNext() {
631              return iterator.hasNext();
632            }
633            @Override
634            public Collection<V> next() {
635              return unmodifiableValueCollection(iterator.next());
636            }
637            @Override
638            public void remove() {
639              throw new UnsupportedOperationException();
640            }
641          };
642        }
643        @Override public Object[] toArray() {
644          return standardToArray();
645        }
646        @Override public <T> T[] toArray(T[] array) {
647          return standardToArray(array);
648        }
649        @Override public boolean contains(Object o) {
650          return standardContains(o);
651        }
652        @Override public boolean containsAll(Collection<?> c) {
653          return standardContainsAll(c);
654        }
655      }
656    
657      private static class UnmodifiableListMultimap<K, V>
658          extends UnmodifiableMultimap<K, V> implements ListMultimap<K, V> {
659        UnmodifiableListMultimap(ListMultimap<K, V> delegate) {
660          super(delegate);
661        }
662        @Override public ListMultimap<K, V> delegate() {
663          return (ListMultimap<K, V>) super.delegate();
664        }
665        @Override public List<V> get(K key) {
666          return Collections.unmodifiableList(delegate().get(key));
667        }
668        @Override public List<V> removeAll(Object key) {
669          throw new UnsupportedOperationException();
670        }
671        @Override public List<V> replaceValues(
672            K key, Iterable<? extends V> values) {
673          throw new UnsupportedOperationException();
674        }
675        private static final long serialVersionUID = 0;
676      }
677    
678      private static class UnmodifiableSetMultimap<K, V>
679          extends UnmodifiableMultimap<K, V> implements SetMultimap<K, V> {
680        UnmodifiableSetMultimap(SetMultimap<K, V> delegate) {
681          super(delegate);
682        }
683        @Override public SetMultimap<K, V> delegate() {
684          return (SetMultimap<K, V>) super.delegate();
685        }
686        @Override public Set<V> get(K key) {
687          /*
688           * Note that this doesn't return a SortedSet when delegate is a
689           * SortedSetMultiset, unlike (SortedSet<V>) super.get().
690           */
691          return Collections.unmodifiableSet(delegate().get(key));
692        }
693        @Override public Set<Map.Entry<K, V>> entries() {
694          return Maps.unmodifiableEntrySet(delegate().entries());
695        }
696        @Override public Set<V> removeAll(Object key) {
697          throw new UnsupportedOperationException();
698        }
699        @Override public Set<V> replaceValues(
700            K key, Iterable<? extends V> values) {
701          throw new UnsupportedOperationException();
702        }
703        private static final long serialVersionUID = 0;
704      }
705    
706      private static class UnmodifiableSortedSetMultimap<K, V>
707          extends UnmodifiableSetMultimap<K, V> implements SortedSetMultimap<K, V> {
708        UnmodifiableSortedSetMultimap(SortedSetMultimap<K, V> delegate) {
709          super(delegate);
710        }
711        @Override public SortedSetMultimap<K, V> delegate() {
712          return (SortedSetMultimap<K, V>) super.delegate();
713        }
714        @Override public SortedSet<V> get(K key) {
715          return Collections.unmodifiableSortedSet(delegate().get(key));
716        }
717        @Override public SortedSet<V> removeAll(Object key) {
718          throw new UnsupportedOperationException();
719        }
720        @Override public SortedSet<V> replaceValues(
721            K key, Iterable<? extends V> values) {
722          throw new UnsupportedOperationException();
723        }
724        @Override
725        public Comparator<? super V> valueComparator() {
726          return delegate().valueComparator();
727        }
728        private static final long serialVersionUID = 0;
729      }
730    
731      /**
732       * Returns a synchronized (thread-safe) {@code SetMultimap} backed by the
733       * specified multimap.
734       *
735       * <p>You must follow the warnings described in {@link #synchronizedMultimap}.
736       *
737       * <p>The returned multimap will be serializable if the specified multimap is
738       * serializable.
739       *
740       * @param multimap the multimap to be wrapped
741       * @return a synchronized view of the specified multimap
742       */
743      public static <K, V> SetMultimap<K, V> synchronizedSetMultimap(
744          SetMultimap<K, V> multimap) {
745        return Synchronized.setMultimap(multimap, null);
746      }
747    
748      /**
749       * Returns an unmodifiable view of the specified {@code SetMultimap}. Query
750       * operations on the returned multimap "read through" to the specified
751       * multimap, and attempts to modify the returned multimap, either directly or
752       * through the multimap's views, result in an
753       * {@code UnsupportedOperationException}.
754       *
755       * <p>Note that the generated multimap's {@link Multimap#removeAll} and
756       * {@link Multimap#replaceValues} methods return collections that are
757       * modifiable.
758       *
759       * <p>The returned multimap will be serializable if the specified multimap is
760       * serializable.
761       *
762       * @param delegate the multimap for which an unmodifiable view is to be
763       *     returned
764       * @return an unmodifiable view of the specified multimap
765       */
766      public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(
767          SetMultimap<K, V> delegate) {
768        if (delegate instanceof UnmodifiableSetMultimap ||
769            delegate instanceof ImmutableSetMultimap) {
770          return delegate;
771        }
772        return new UnmodifiableSetMultimap<K, V>(delegate);
773      }
774    
775      /**
776       * Simply returns its argument.
777       *
778       * @deprecated no need to use this
779       * @since 10.0
780       */
781      @Deprecated public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(
782          ImmutableSetMultimap<K, V> delegate) {
783        return checkNotNull(delegate);
784      }
785    
786      /**
787       * Returns a synchronized (thread-safe) {@code SortedSetMultimap} backed by
788       * the specified multimap.
789       *
790       * <p>You must follow the warnings described in {@link #synchronizedMultimap}.
791       *
792       * <p>The returned multimap will be serializable if the specified multimap is
793       * serializable.
794       *
795       * @param multimap the multimap to be wrapped
796       * @return a synchronized view of the specified multimap
797       */
798      public static <K, V> SortedSetMultimap<K, V>
799          synchronizedSortedSetMultimap(SortedSetMultimap<K, V> multimap) {
800        return Synchronized.sortedSetMultimap(multimap, null);
801      }
802    
803      /**
804       * Returns an unmodifiable view of the specified {@code SortedSetMultimap}.
805       * Query operations on the returned multimap "read through" to the specified
806       * multimap, and attempts to modify the returned multimap, either directly or
807       * through the multimap's views, result in an
808       * {@code UnsupportedOperationException}.
809       *
810       * <p>Note that the generated multimap's {@link Multimap#removeAll} and
811       * {@link Multimap#replaceValues} methods return collections that are
812       * modifiable.
813       *
814       * <p>The returned multimap will be serializable if the specified multimap is
815       * serializable.
816       *
817       * @param delegate the multimap for which an unmodifiable view is to be
818       *     returned
819       * @return an unmodifiable view of the specified multimap
820       */
821      public static <K, V> SortedSetMultimap<K, V> unmodifiableSortedSetMultimap(
822          SortedSetMultimap<K, V> delegate) {
823        if (delegate instanceof UnmodifiableSortedSetMultimap) {
824          return delegate;
825        }
826        return new UnmodifiableSortedSetMultimap<K, V>(delegate);
827      }
828    
829      /**
830       * Returns a synchronized (thread-safe) {@code ListMultimap} backed by the
831       * specified multimap.
832       *
833       * <p>You must follow the warnings described in {@link #synchronizedMultimap}.
834       *
835       * @param multimap the multimap to be wrapped
836       * @return a synchronized view of the specified multimap
837       */
838      public static <K, V> ListMultimap<K, V> synchronizedListMultimap(
839          ListMultimap<K, V> multimap) {
840        return Synchronized.listMultimap(multimap, null);
841      }
842    
843      /**
844       * Returns an unmodifiable view of the specified {@code ListMultimap}. Query
845       * operations on the returned multimap "read through" to the specified
846       * multimap, and attempts to modify the returned multimap, either directly or
847       * through the multimap's views, result in an
848       * {@code UnsupportedOperationException}.
849       *
850       * <p>Note that the generated multimap's {@link Multimap#removeAll} and
851       * {@link Multimap#replaceValues} methods return collections that are
852       * modifiable.
853       *
854       * <p>The returned multimap will be serializable if the specified multimap is
855       * serializable.
856       *
857       * @param delegate the multimap for which an unmodifiable view is to be
858       *     returned
859       * @return an unmodifiable view of the specified multimap
860       */
861      public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(
862          ListMultimap<K, V> delegate) {
863        if (delegate instanceof UnmodifiableListMultimap ||
864            delegate instanceof ImmutableListMultimap) {
865          return delegate;
866        }
867        return new UnmodifiableListMultimap<K, V>(delegate);
868      }
869    
870      /**
871       * Simply returns its argument.
872       *
873       * @deprecated no need to use this
874       * @since 10.0
875       */
876      @Deprecated public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(
877          ImmutableListMultimap<K, V> delegate) {
878        return checkNotNull(delegate);
879      }
880    
881      /**
882       * Returns an unmodifiable view of the specified collection, preserving the
883       * interface for instances of {@code SortedSet}, {@code Set}, {@code List} and
884       * {@code Collection}, in that order of preference.
885       *
886       * @param collection the collection for which to return an unmodifiable view
887       * @return an unmodifiable view of the collection
888       */
889      private static <V> Collection<V> unmodifiableValueCollection(
890          Collection<V> collection) {
891        if (collection instanceof SortedSet) {
892          return Collections.unmodifiableSortedSet((SortedSet<V>) collection);
893        } else if (collection instanceof Set) {
894          return Collections.unmodifiableSet((Set<V>) collection);
895        } else if (collection instanceof List) {
896          return Collections.unmodifiableList((List<V>) collection);
897        }
898        return Collections.unmodifiableCollection(collection);
899      }
900    
901      /**
902       * Returns an unmodifiable view of the specified multimap {@code asMap} entry.
903       * The {@link Entry#setValue} operation throws an {@link
904       * UnsupportedOperationException}, and the collection returned by {@code
905       * getValue} is also an unmodifiable (type-preserving) view. This also has the
906       * side-effect of redefining equals to comply with the Map.Entry contract, and
907       * to avoid a possible nefarious implementation of equals.
908       *
909       * @param entry the entry for which to return an unmodifiable view
910       * @return an unmodifiable view of the entry
911       */
912      private static <K, V> Map.Entry<K, Collection<V>> unmodifiableAsMapEntry(
913          final Map.Entry<K, Collection<V>> entry) {
914        checkNotNull(entry);
915        return new AbstractMapEntry<K, Collection<V>>() {
916          @Override public K getKey() {
917            return entry.getKey();
918          }
919    
920          @Override public Collection<V> getValue() {
921            return unmodifiableValueCollection(entry.getValue());
922          }
923        };
924      }
925    
926      /**
927       * Returns an unmodifiable view of the specified collection of entries. The
928       * {@link Entry#setValue} operation throws an {@link
929       * UnsupportedOperationException}. If the specified collection is a {@code
930       * Set}, the returned collection is also a {@code Set}.
931       *
932       * @param entries the entries for which to return an unmodifiable view
933       * @return an unmodifiable view of the entries
934       */
935      private static <K, V> Collection<Entry<K, V>> unmodifiableEntries(
936          Collection<Entry<K, V>> entries) {
937        if (entries instanceof Set) {
938          return Maps.unmodifiableEntrySet((Set<Entry<K, V>>) entries);
939        }
940        return new Maps.UnmodifiableEntries<K, V>(
941            Collections.unmodifiableCollection(entries));
942      }
943    
944      /**
945       * Returns an unmodifiable view of the specified set of {@code asMap} entries.
946       * The {@link Entry#setValue} operation throws an {@link
947       * UnsupportedOperationException}, as do any operations that attempt to modify
948       * the returned collection.
949       *
950       * @param asMapEntries the {@code asMap} entries for which to return an
951       *     unmodifiable view
952       * @return an unmodifiable view of the collection entries
953       */
954      private static <K, V> Set<Entry<K, Collection<V>>> unmodifiableAsMapEntries(
955          Set<Entry<K, Collection<V>>> asMapEntries) {
956        return new UnmodifiableAsMapEntries<K, V>(
957            Collections.unmodifiableSet(asMapEntries));
958      }
959    
960      /** @see Multimaps#unmodifiableAsMapEntries */
961      static class UnmodifiableAsMapEntries<K, V>
962          extends ForwardingSet<Entry<K, Collection<V>>> {
963        private final Set<Entry<K, Collection<V>>> delegate;
964        UnmodifiableAsMapEntries(Set<Entry<K, Collection<V>>> delegate) {
965          this.delegate = delegate;
966        }
967    
968        @Override protected Set<Entry<K, Collection<V>>> delegate() {
969          return delegate;
970        }
971    
972        @Override public Iterator<Entry<K, Collection<V>>> iterator() {
973          final Iterator<Entry<K, Collection<V>>> iterator = delegate.iterator();
974          return new ForwardingIterator<Entry<K, Collection<V>>>() {
975            @Override protected Iterator<Entry<K, Collection<V>>> delegate() {
976              return iterator;
977            }
978            @Override public Entry<K, Collection<V>> next() {
979              return unmodifiableAsMapEntry(iterator.next());
980            }
981          };
982        }
983    
984        @Override public Object[] toArray() {
985          return standardToArray();
986        }
987    
988        @Override public <T> T[] toArray(T[] array) {
989          return standardToArray(array);
990        }
991    
992        @Override public boolean contains(Object o) {
993          return Maps.containsEntryImpl(delegate(), o);
994        }
995    
996        @Override public boolean containsAll(Collection<?> c) {
997          return standardContainsAll(c);
998        }
999    
1000        @Override public boolean equals(@Nullable Object object) {
1001          return standardEquals(object);
1002        }
1003      }
1004    
1005      /**
1006       * Returns a multimap view of the specified map. The multimap is backed by the
1007       * map, so changes to the map are reflected in the multimap, and vice versa.
1008       * If the map is modified while an iteration over one of the multimap's
1009       * collection views is in progress (except through the iterator's own {@code
1010       * remove} operation, or through the {@code setValue} operation on a map entry
1011       * returned by the iterator), the results of the iteration are undefined.
1012       *
1013       * <p>The multimap supports mapping removal, which removes the corresponding
1014       * mapping from the map. It does not support any operations which might add
1015       * mappings, such as {@code put}, {@code putAll} or {@code replaceValues}.
1016       *
1017       * <p>The returned multimap will be serializable if the specified map is
1018       * serializable.
1019       *
1020       * @param map the backing map for the returned multimap view
1021       */
1022      public static <K, V> SetMultimap<K, V> forMap(Map<K, V> map) {
1023        return new MapMultimap<K, V>(map);
1024      }
1025    
1026      /** @see Multimaps#forMap */
1027      private static class MapMultimap<K, V>
1028          implements SetMultimap<K, V>, Serializable {
1029        final Map<K, V> map;
1030        transient Map<K, Collection<V>> asMap;
1031    
1032        MapMultimap(Map<K, V> map) {
1033          this.map = checkNotNull(map);
1034        }
1035    
1036        @Override
1037        public int size() {
1038          return map.size();
1039        }
1040    
1041        @Override
1042        public boolean isEmpty() {
1043          return map.isEmpty();
1044        }
1045    
1046        @Override
1047        public boolean containsKey(Object key) {
1048          return map.containsKey(key);
1049        }
1050    
1051        @Override
1052        public boolean containsValue(Object value) {
1053          return map.containsValue(value);
1054        }
1055    
1056        @Override
1057        public boolean containsEntry(Object key, Object value) {
1058          return map.entrySet().contains(Maps.immutableEntry(key, value));
1059        }
1060    
1061        @Override
1062        public Set<V> get(final K key) {
1063          return new AbstractSet<V>() {
1064            @Override public Iterator<V> iterator() {
1065              return new Iterator<V>() {
1066                int i;
1067    
1068                @Override
1069                public boolean hasNext() {
1070                  return (i == 0) && map.containsKey(key);
1071                }
1072    
1073                @Override
1074                public V next() {
1075                  if (!hasNext()) {
1076                    throw new NoSuchElementException();
1077                  }
1078                  i++;
1079                  return map.get(key);
1080                }
1081    
1082                @Override
1083                public void remove() {
1084                  checkState(i == 1);
1085                  i = -1;
1086                  map.remove(key);
1087                }
1088              };
1089            }
1090    
1091            @Override public int size() {
1092              return map.containsKey(key) ? 1 : 0;
1093            }
1094          };
1095        }
1096    
1097        @Override
1098        public boolean put(K key, V value) {
1099          throw new UnsupportedOperationException();
1100        }
1101    
1102        @Override
1103        public boolean putAll(K key, Iterable<? extends V> values) {
1104          throw new UnsupportedOperationException();
1105        }
1106    
1107        @Override
1108        public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
1109          throw new UnsupportedOperationException();
1110        }
1111    
1112        @Override
1113        public Set<V> replaceValues(K key, Iterable<? extends V> values) {
1114          throw new UnsupportedOperationException();
1115        }
1116    
1117        @Override
1118        public boolean remove(Object key, Object value) {
1119          return map.entrySet().remove(Maps.immutableEntry(key, value));
1120        }
1121    
1122        @Override
1123        public Set<V> removeAll(Object key) {
1124          Set<V> values = new HashSet<V>(2);
1125          if (!map.containsKey(key)) {
1126            return values;
1127          }
1128          values.add(map.remove(key));
1129          return values;
1130        }
1131    
1132        @Override
1133        public void clear() {
1134          map.clear();
1135        }
1136    
1137        @Override
1138        public Set<K> keySet() {
1139          return map.keySet();
1140        }
1141    
1142        @Override
1143        public Multiset<K> keys() {
1144          return Multisets.forSet(map.keySet());
1145        }
1146    
1147        @Override
1148        public Collection<V> values() {
1149          return map.values();
1150        }
1151    
1152        @Override
1153        public Set<Entry<K, V>> entries() {
1154          return map.entrySet();
1155        }
1156    
1157        @Override
1158        public Map<K, Collection<V>> asMap() {
1159          Map<K, Collection<V>> result = asMap;
1160          if (result == null) {
1161            asMap = result = new AsMap();
1162          }
1163          return result;
1164        }
1165    
1166        @Override public boolean equals(@Nullable Object object) {
1167          if (object == this) {
1168            return true;
1169          }
1170          if (object instanceof Multimap) {
1171            Multimap<?, ?> that = (Multimap<?, ?>) object;
1172            return this.size() == that.size() && asMap().equals(that.asMap());
1173          }
1174          return false;
1175        }
1176    
1177        @Override public int hashCode() {
1178          return map.hashCode();
1179        }
1180    
1181        private static final MapJoiner JOINER
1182            = Joiner.on("], ").withKeyValueSeparator("=[").useForNull("null");
1183    
1184        @Override public String toString() {
1185          if (map.isEmpty()) {
1186            return "{}";
1187          }
1188          StringBuilder builder
1189              = Collections2.newStringBuilderForCollection(map.size()).append('{');
1190          JOINER.appendTo(builder, map);
1191          return builder.append("]}").toString();
1192        }
1193    
1194        /** @see MapMultimap#asMap */
1195        class AsMapEntries extends AbstractSet<Entry<K, Collection<V>>> {
1196          @Override public int size() {
1197            return map.size();
1198          }
1199    
1200          @Override public Iterator<Entry<K, Collection<V>>> iterator() {
1201            return new Iterator<Entry<K, Collection<V>>>() {
1202              final Iterator<K> keys = map.keySet().iterator();
1203    
1204              @Override
1205              public boolean hasNext() {
1206                return keys.hasNext();
1207              }
1208              @Override
1209              public Entry<K, Collection<V>> next() {
1210                final K key = keys.next();
1211                return new AbstractMapEntry<K, Collection<V>>() {
1212                  @Override public K getKey() {
1213                    return key;
1214                  }
1215                  @Override public Collection<V> getValue() {
1216                    return get(key);
1217                  }
1218                };
1219              }
1220              @Override
1221              public void remove() {
1222                keys.remove();
1223              }
1224            };
1225          }
1226    
1227          @Override public boolean contains(Object o) {
1228            if (!(o instanceof Entry)) {
1229              return false;
1230            }
1231            Entry<?, ?> entry = (Entry<?, ?>) o;
1232            if (!(entry.getValue() instanceof Set)) {
1233              return false;
1234            }
1235            Set<?> set = (Set<?>) entry.getValue();
1236            return (set.size() == 1)
1237                && containsEntry(entry.getKey(), set.iterator().next());
1238          }
1239    
1240          @Override public boolean remove(Object o) {
1241            if (!(o instanceof Entry)) {
1242              return false;
1243            }
1244            Entry<?, ?> entry = (Entry<?, ?>) o;
1245            if (!(entry.getValue() instanceof Set)) {
1246              return false;
1247            }
1248            Set<?> set = (Set<?>) entry.getValue();
1249            return (set.size() == 1)
1250                && map.entrySet().remove(
1251                    Maps.immutableEntry(entry.getKey(), set.iterator().next()));
1252          }
1253        }
1254    
1255        /** @see MapMultimap#asMap */
1256        class AsMap extends Maps.ImprovedAbstractMap<K, Collection<V>> {
1257          @Override protected Set<Entry<K, Collection<V>>> createEntrySet() {
1258            return new AsMapEntries();
1259          }
1260    
1261          // The following methods are included for performance.
1262    
1263          @Override public boolean containsKey(Object key) {
1264            return map.containsKey(key);
1265          }
1266    
1267          @SuppressWarnings("unchecked")
1268          @Override public Collection<V> get(Object key) {
1269            Collection<V> collection = MapMultimap.this.get((K) key);
1270            return collection.isEmpty() ? null : collection;
1271          }
1272    
1273          @Override public Collection<V> remove(Object key) {
1274            Collection<V> collection = removeAll(key);
1275            return collection.isEmpty() ? null : collection;
1276          }
1277        }
1278        private static final long serialVersionUID = 7845222491160860175L;
1279      }
1280    
1281      /**
1282       * Returns a view of a multimap where each value is transformed by a function.
1283       * All other properties of the multimap, such as iteration order, are left
1284       * intact. For example, the code: <pre>   {@code
1285       *
1286       * Multimap<String, Integer> multimap =
1287       *     ImmutableSetMultimap.of("a", 2, "b", -3, "b", -3, "a", 4, "c", 6);
1288       * Function<Integer, String> square = new Function<Integer, String>() {
1289       *     public String apply(Integer in) {
1290       *       return Integer.toString(in * in);
1291       *     }
1292       * };
1293       * Multimap<String, String> transformed =
1294       *     Multimaps.transformValues(multimap, square);
1295       *   System.out.println(transformed);}</pre>
1296       *
1297       * ... prints {@code {a=[4, 16], b=[9, 9], c=[6]}}.
1298       *
1299       * <p>Changes in the underlying multimap are reflected in this view.
1300       * Conversely, this view supports removal operations, and these are reflected
1301       * in the underlying multimap.
1302       *
1303       * <p>It's acceptable for the underlying multimap to contain null keys, and
1304       * even null values provided that the function is capable of accepting null
1305       * input.  The transformed multimap might contain null values, if the function
1306       * sometimes gives a null result.
1307       *
1308       * <p>The returned multimap is not thread-safe or serializable, even if the
1309       * underlying multimap is.  The {@code equals} and {@code hashCode} methods
1310       * of the returned multimap are meaningless, since there is not a definition
1311       * of {@code equals} or {@code hashCode} for general collections, and
1312       * {@code get()} will return a general {@code Collection} as opposed to a
1313       * {@code List} or a {@code Set}.
1314       *
1315       * <p>The function is applied lazily, invoked when needed. This is necessary
1316       * for the returned multimap to be a view, but it means that the function will
1317       * be applied many times for bulk operations like
1318       * {@link Multimap#containsValue} and {@code Multimap.toString()}. For this to
1319       * perform well, {@code function} should be fast. To avoid lazy evaluation
1320       * when the returned multimap doesn't need to be a view, copy the returned
1321       * multimap into a new multimap of your choosing.
1322       *
1323       * @since 7.0
1324       */
1325      @Beta
1326      public static <K, V1, V2> Multimap<K, V2> transformValues(
1327          Multimap<K, V1> fromMultimap, final Function<? super V1, V2> function) {
1328        checkNotNull(function);
1329        EntryTransformer<K, V1, V2> transformer =
1330            new EntryTransformer<K, V1, V2>() {
1331              @Override
1332              public V2 transformEntry(K key, V1 value) {
1333                return function.apply(value);
1334              }
1335            };
1336        return transformEntries(fromMultimap, transformer);
1337      }
1338    
1339      /**
1340       * Returns a view of a multimap whose values are derived from the original
1341       * multimap's entries. In contrast to {@link #transformValues}, this method's
1342       * entry-transformation logic may depend on the key as well as the value.
1343       *
1344       * <p>All other properties of the transformed multimap, such as iteration
1345       * order, are left intact. For example, the code: <pre>   {@code
1346       *
1347       *   SetMultimap<String, Integer> multimap =
1348       *       ImmutableSetMultimap.of("a", 1, "a", 4, "b", -6);
1349       *   EntryTransformer<String, Integer, String> transformer =
1350       *       new EntryTransformer<String, Integer, String>() {
1351       *         public String transformEntry(String key, Integer value) {
1352       *            return (value >= 0) ? key : "no" + key;
1353       *         }
1354       *       };
1355       *   Multimap<String, String> transformed =
1356       *       Multimaps.transformEntries(multimap, transformer);
1357       *   System.out.println(transformed);}</pre>
1358       *
1359       * ... prints {@code {a=[a, a], b=[nob]}}.
1360       *
1361       * <p>Changes in the underlying multimap are reflected in this view.
1362       * Conversely, this view supports removal operations, and these are reflected
1363       * in the underlying multimap.
1364       *
1365       * <p>It's acceptable for the underlying multimap to contain null keys and
1366       * null values provided that the transformer is capable of accepting null
1367       * inputs. The transformed multimap might contain null values if the
1368       * transformer sometimes gives a null result.
1369       *
1370       * <p>The returned multimap is not thread-safe or serializable, even if the
1371       * underlying multimap is.  The {@code equals} and {@code hashCode} methods
1372       * of the returned multimap are meaningless, since there is not a definition
1373       * of {@code equals} or {@code hashCode} for general collections, and
1374       * {@code get()} will return a general {@code Collection} as opposed to a
1375       * {@code List} or a {@code Set}.
1376       *
1377       * <p>The transformer is applied lazily, invoked when needed. This is
1378       * necessary for the returned multimap to be a view, but it means that the
1379       * transformer will be applied many times for bulk operations like {@link
1380       * Multimap#containsValue} and {@link Object#toString}. For this to perform
1381       * well, {@code transformer} should be fast. To avoid lazy evaluation when the
1382       * returned multimap doesn't need to be a view, copy the returned multimap
1383       * into a new multimap of your choosing.
1384       *
1385       * <p><b>Warning:</b> This method assumes that for any instance {@code k} of
1386       * {@code EntryTransformer} key type {@code K}, {@code k.equals(k2)} implies
1387       * that {@code k2} is also of type {@code K}. Using an {@code
1388       * EntryTransformer} key type for which this may not hold, such as {@code
1389       * ArrayList}, may risk a {@code ClassCastException} when calling methods on
1390       * the transformed multimap.
1391       *
1392       * @since 7.0
1393       */
1394      @Beta
1395      public static <K, V1, V2> Multimap<K, V2> transformEntries(
1396          Multimap<K, V1> fromMap,
1397          EntryTransformer<? super K, ? super V1, V2> transformer) {
1398        return new TransformedEntriesMultimap<K, V1, V2>(fromMap, transformer);
1399      }
1400    
1401      private static class TransformedEntriesMultimap<K, V1, V2>
1402          implements Multimap<K, V2> {
1403        final Multimap<K, V1> fromMultimap;
1404        final EntryTransformer<? super K, ? super V1, V2> transformer;
1405    
1406        TransformedEntriesMultimap(Multimap<K, V1> fromMultimap,
1407            final EntryTransformer<? super K, ? super V1, V2> transformer) {
1408          this.fromMultimap = checkNotNull(fromMultimap);
1409          this.transformer = checkNotNull(transformer);
1410        }
1411    
1412        Collection<V2> transform(final K key, Collection<V1> values) {
1413          return Collections2.transform(values, new Function<V1, V2>() {
1414            @Override public V2 apply(V1 value) {
1415              return transformer.transformEntry(key, value);
1416            }
1417          });
1418        }
1419    
1420        private transient Map<K, Collection<V2>> asMap;
1421    
1422        @Override public Map<K, Collection<V2>> asMap() {
1423          if (asMap == null) {
1424            Map<K, Collection<V2>> aM = Maps.transformEntries(fromMultimap.asMap(),
1425                new EntryTransformer<K, Collection<V1>, Collection<V2>>() {
1426    
1427                  @Override public Collection<V2> transformEntry(
1428                      K key, Collection<V1> value) {
1429                    return transform(key, value);
1430                  }
1431                });
1432            asMap = aM;
1433            return aM;
1434          }
1435          return asMap;
1436        }
1437    
1438        @Override public void clear() {
1439          fromMultimap.clear();
1440        }
1441    
1442        @SuppressWarnings("unchecked")
1443        @Override public boolean containsEntry(Object key, Object value) {
1444          Collection<V2> values = get((K) key);
1445          return values.contains(value);
1446        }
1447    
1448        @Override public boolean containsKey(Object key) {
1449          return fromMultimap.containsKey(key);
1450        }
1451    
1452        @Override public boolean containsValue(Object value) {
1453          return values().contains(value);
1454        }
1455    
1456        private transient Collection<Entry<K, V2>> entries;
1457    
1458        @Override public Collection<Entry<K, V2>> entries() {
1459          if (entries == null) {
1460            Collection<Entry<K, V2>> es = new TransformedEntries(transformer);
1461            entries = es;
1462            return es;
1463          }
1464          return entries;
1465        }
1466    
1467        private class TransformedEntries
1468            extends TransformedCollection<Entry<K, V1>, Entry<K, V2>> {
1469    
1470          TransformedEntries(
1471              final EntryTransformer<? super K, ? super V1, V2> transformer) {
1472            super(fromMultimap.entries(),
1473                new Function<Entry<K, V1>, Entry<K, V2>>() {
1474                  @Override public Entry<K, V2> apply(final Entry<K, V1> entry) {
1475                    return new AbstractMapEntry<K, V2>() {
1476    
1477                      @Override public K getKey() {
1478                        return entry.getKey();
1479                      }
1480    
1481                      @Override public V2 getValue() {
1482                        return transformer.transformEntry(
1483                            entry.getKey(), entry.getValue());
1484                      }
1485                    };
1486                  }
1487                });
1488          }
1489    
1490          @Override public boolean contains(Object o) {
1491            if (o instanceof Entry) {
1492              Entry<?, ?> entry = (Entry<?, ?>) o;
1493              return containsEntry(entry.getKey(), entry.getValue());
1494            }
1495            return false;
1496          }
1497    
1498          @SuppressWarnings("unchecked")
1499          @Override public boolean remove(Object o) {
1500            if (o instanceof Entry) {
1501              Entry<?, ?> entry = (Entry<?, ?>) o;
1502              Collection<V2> values = get((K) entry.getKey());
1503              return values.remove(entry.getValue());
1504            }
1505            return false;
1506          }
1507    
1508        }
1509    
1510        @Override public Collection<V2> get(final K key) {
1511          return transform(key, fromMultimap.get(key));
1512        }
1513    
1514        @Override public boolean isEmpty() {
1515          return fromMultimap.isEmpty();
1516        }
1517    
1518        @Override public Set<K> keySet() {
1519          return fromMultimap.keySet();
1520        }
1521    
1522        @Override public Multiset<K> keys() {
1523          return fromMultimap.keys();
1524        }
1525    
1526        @Override public boolean put(K key, V2 value) {
1527          throw new UnsupportedOperationException();
1528        }
1529    
1530        @Override public boolean putAll(K key, Iterable<? extends V2> values) {
1531          throw new UnsupportedOperationException();
1532        }
1533    
1534        @Override public boolean putAll(
1535            Multimap<? extends K, ? extends V2> multimap) {
1536          throw new UnsupportedOperationException();
1537        }
1538    
1539        @SuppressWarnings("unchecked")
1540        @Override public boolean remove(Object key, Object value) {
1541          return get((K) key).remove(value);
1542        }
1543    
1544        @SuppressWarnings("unchecked")
1545        @Override public Collection<V2> removeAll(Object key) {
1546          return transform((K) key, fromMultimap.removeAll(key));
1547        }
1548    
1549        @Override public Collection<V2> replaceValues(
1550            K key, Iterable<? extends V2> values) {
1551          throw new UnsupportedOperationException();
1552        }
1553    
1554        @Override public int size() {
1555          return fromMultimap.size();
1556        }
1557    
1558        private transient Collection<V2> values;
1559    
1560        @Override public Collection<V2> values() {
1561          if (values == null) {
1562            Collection<V2> vs = Collections2.transform(
1563                fromMultimap.entries(), new Function<Entry<K, V1>, V2>() {
1564    
1565                  @Override public V2 apply(Entry<K, V1> entry) {
1566                    return transformer.transformEntry(
1567                        entry.getKey(), entry.getValue());
1568                  }
1569                });
1570            values = vs;
1571            return vs;
1572          }
1573          return values;
1574        }
1575    
1576        @Override public boolean equals(Object obj) {
1577          if (obj instanceof Multimap) {
1578            Multimap<?, ?> other = (Multimap<?, ?>) obj;
1579            return asMap().equals(other.asMap());
1580          }
1581          return false;
1582        }
1583    
1584        @Override public int hashCode() {
1585          return asMap().hashCode();
1586        }
1587    
1588        @Override public String toString() {
1589          return asMap().toString();
1590        }
1591      }
1592    
1593      /**
1594       * Returns a view of a {@code ListMultimap} where each value is transformed by
1595       * a function. All other properties of the multimap, such as iteration order,
1596       * are left intact. For example, the code: <pre>   {@code
1597       *
1598       *   ListMultimap<String, Integer> multimap
1599       *        = ImmutableListMultimap.of("a", 4, "a", 16, "b", 9);
1600       *   Function<Integer, Double> sqrt =
1601       *       new Function<Integer, Double>() {
1602       *         public Double apply(Integer in) {
1603       *           return Math.sqrt((int) in);
1604       *         }
1605       *       };
1606       *   ListMultimap<String, Double> transformed = Multimaps.transformValues(map,
1607       *       sqrt);
1608       *   System.out.println(transformed);}</pre>
1609       *
1610       * ... prints {@code {a=[2.0, 4.0], b=[3.0]}}.
1611       *
1612       * <p>Changes in the underlying multimap are reflected in this view.
1613       * Conversely, this view supports removal operations, and these are reflected
1614       * in the underlying multimap.
1615       *
1616       * <p>It's acceptable for the underlying multimap to contain null keys, and
1617       * even null values provided that the function is capable of accepting null
1618       * input.  The transformed multimap might contain null values, if the function
1619       * sometimes gives a null result.
1620       *
1621       * <p>The returned multimap is not thread-safe or serializable, even if the
1622       * underlying multimap is.
1623       *
1624       * <p>The function is applied lazily, invoked when needed. This is necessary
1625       * for the returned multimap to be a view, but it means that the function will
1626       * be applied many times for bulk operations like
1627       * {@link Multimap#containsValue} and {@code Multimap.toString()}. For this to
1628       * perform well, {@code function} should be fast. To avoid lazy evaluation
1629       * when the returned multimap doesn't need to be a view, copy the returned
1630       * multimap into a new multimap of your choosing.
1631       *
1632       * @since 7.0
1633       */
1634      @Beta
1635      public static <K, V1, V2> ListMultimap<K, V2> transformValues(
1636          ListMultimap<K, V1> fromMultimap,
1637          final Function<? super V1, V2> function) {
1638        checkNotNull(function);
1639        EntryTransformer<K, V1, V2> transformer =
1640            new EntryTransformer<K, V1, V2>() {
1641              @Override
1642              public V2 transformEntry(K key, V1 value) {
1643                return function.apply(value);
1644              }
1645            };
1646        return transformEntries(fromMultimap, transformer);
1647      }
1648    
1649      /**
1650       * Returns a view of a {@code ListMultimap} whose values are derived from the
1651       * original multimap's entries. In contrast to
1652       * {@link #transformValues(ListMultimap, Function)}, this method's
1653       * entry-transformation logic may depend on the key as well as the value.
1654       *
1655       * <p>All other properties of the transformed multimap, such as iteration
1656       * order, are left intact. For example, the code: <pre>   {@code
1657       *
1658       *   Multimap<String, Integer> multimap =
1659       *       ImmutableMultimap.of("a", 1, "a", 4, "b", 6);
1660       *   EntryTransformer<String, Integer, String> transformer =
1661       *       new EntryTransformer<String, Integer, String>() {
1662       *         public String transformEntry(String key, Integer value) {
1663       *           return key + value;
1664       *         }
1665       *       };
1666       *   Multimap<String, String> transformed =
1667       *       Multimaps.transformEntries(multimap, transformer);
1668       *   System.out.println(transformed);}</pre>
1669       *
1670       * ... prints {@code {"a"=["a1", "a4"], "b"=["b6"]}}.
1671       *
1672       * <p>Changes in the underlying multimap are reflected in this view.
1673       * Conversely, this view supports removal operations, and these are reflected
1674       * in the underlying multimap.
1675       *
1676       * <p>It's acceptable for the underlying multimap to contain null keys and
1677       * null values provided that the transformer is capable of accepting null
1678       * inputs. The transformed multimap might contain null values if the
1679       * transformer sometimes gives a null result.
1680       *
1681       * <p>The returned multimap is not thread-safe or serializable, even if the
1682       * underlying multimap is.
1683       *
1684       * <p>The transformer is applied lazily, invoked when needed. This is
1685       * necessary for the returned multimap to be a view, but it means that the
1686       * transformer will be applied many times for bulk operations like {@link
1687       * Multimap#containsValue} and {@link Object#toString}. For this to perform
1688       * well, {@code transformer} should be fast. To avoid lazy evaluation when the
1689       * returned multimap doesn't need to be a view, copy the returned multimap
1690       * into a new multimap of your choosing.
1691       *
1692       * <p><b>Warning:</b> This method assumes that for any instance {@code k} of
1693       * {@code EntryTransformer} key type {@code K}, {@code k.equals(k2)} implies
1694       * that {@code k2} is also of type {@code K}. Using an {@code
1695       * EntryTransformer} key type for which this may not hold, such as {@code
1696       * ArrayList}, may risk a {@code ClassCastException} when calling methods on
1697       * the transformed multimap.
1698       *
1699       * @since 7.0
1700       */
1701      @Beta
1702      public static <K, V1, V2> ListMultimap<K, V2> transformEntries(
1703          ListMultimap<K, V1> fromMap,
1704          EntryTransformer<? super K, ? super V1, V2> transformer) {
1705        return new TransformedEntriesListMultimap<K, V1, V2>(fromMap, transformer);
1706      }
1707    
1708      private static final class TransformedEntriesListMultimap<K, V1, V2>
1709          extends TransformedEntriesMultimap<K, V1, V2>
1710          implements ListMultimap<K, V2> {
1711    
1712        TransformedEntriesListMultimap(ListMultimap<K, V1> fromMultimap,
1713            EntryTransformer<? super K, ? super V1, V2> transformer) {
1714          super(fromMultimap, transformer);
1715        }
1716    
1717        @Override List<V2> transform(final K key, Collection<V1> values) {
1718          return Lists.transform((List<V1>) values, new Function<V1, V2>() {
1719            @Override public V2 apply(V1 value) {
1720              return transformer.transformEntry(key, value);
1721            }
1722          });
1723        }
1724    
1725        @Override public List<V2> get(K key) {
1726          return transform(key, fromMultimap.get(key));
1727        }
1728    
1729        @SuppressWarnings("unchecked")
1730        @Override public List<V2> removeAll(Object key) {
1731          return transform((K) key, fromMultimap.removeAll(key));
1732        }
1733    
1734        @Override public List<V2> replaceValues(
1735            K key, Iterable<? extends V2> values) {
1736          throw new UnsupportedOperationException();
1737        }
1738      }
1739    
1740      /**
1741       * Creates an index {@code ImmutableListMultimap} that contains the results of
1742       * applying a specified function to each item in an {@code Iterable} of
1743       * values. Each value will be stored as a value in the resulting multimap,
1744       * yielding a multimap with the same size as the input iterable. The key used
1745       * to store that value in the multimap will be the result of calling the
1746       * function on that value. The resulting multimap is created as an immutable
1747       * snapshot. In the returned multimap, keys appear in the order they are first
1748       * encountered, and the values corresponding to each key appear in the same
1749       * order as they are encountered.
1750       *
1751       * <p>For example, <pre>   {@code
1752       *
1753       *   List<String> badGuys =
1754       *       Arrays.asList("Inky", "Blinky", "Pinky", "Pinky", "Clyde");
1755       *   Function<String, Integer> stringLengthFunction = ...;
1756       *   Multimap<Integer, String> index =
1757       *       Multimaps.index(badGuys, stringLengthFunction);
1758       *   System.out.println(index);}</pre>
1759       *
1760       * prints <pre>   {@code
1761       *
1762       *   {4=[Inky], 6=[Blinky], 5=[Pinky, Pinky, Clyde]}}</pre>
1763       *
1764       * The returned multimap is serializable if its keys and values are all
1765       * serializable.
1766       *
1767       * @param values the values to use when constructing the {@code
1768       *     ImmutableListMultimap}
1769       * @param keyFunction the function used to produce the key for each value
1770       * @return {@code ImmutableListMultimap} mapping the result of evaluating the
1771       *     function {@code keyFunction} on each value in the input collection to
1772       *     that value
1773       * @throws NullPointerException if any of the following cases is true:
1774       *     <ul>
1775       *     <li>{@code values} is null
1776       *     <li>{@code keyFunction} is null
1777       *     <li>An element in {@code values} is null
1778       *     <li>{@code keyFunction} returns {@code null} for any element of {@code
1779       *         values}
1780       *     </ul>
1781       */
1782      public static <K, V> ImmutableListMultimap<K, V> index(
1783          Iterable<V> values, Function<? super V, K> keyFunction) {
1784        return index(values.iterator(), keyFunction);
1785      }
1786    
1787      /**
1788       * <b>Deprecated.</b>
1789       *
1790       * @since 10.0
1791       * @deprecated use {@link #index(Iterator, Function)} by casting {@code
1792       *     values} to {@code Iterator<V>}, or better yet, by implementing only
1793       *     {@code Iterator} and not {@code Iterable}. <b>This method is scheduled
1794       *     for deletion in March 2012.</b>
1795       */
1796      @Beta
1797      @Deprecated
1798      public static <K, V, I extends Object & Iterable<V> & Iterator<V>>
1799          ImmutableListMultimap<K, V> index(
1800              I values, Function<? super V, K> keyFunction) {
1801        Iterable<V> valuesIterable = checkNotNull(values);
1802        return index(valuesIterable, keyFunction);
1803      }
1804    
1805      /**
1806       * Creates an index {@code ImmutableListMultimap} that contains the results of
1807       * applying a specified function to each item in an {@code Iterator} of
1808       * values. Each value will be stored as a value in the resulting multimap,
1809       * yielding a multimap with the same size as the input iterator. The key used
1810       * to store that value in the multimap will be the result of calling the
1811       * function on that value. The resulting multimap is created as an immutable
1812       * snapshot. In the returned multimap, keys appear in the order they are first
1813       * encountered, and the values corresponding to each key appear in the same
1814       * order as they are encountered.
1815       *
1816       * <p>For example, <pre>   {@code
1817       *
1818       *   List<String> badGuys =
1819       *       Arrays.asList("Inky", "Blinky", "Pinky", "Pinky", "Clyde");
1820       *   Function<String, Integer> stringLengthFunction = ...;
1821       *   Multimap<Integer, String> index =
1822       *       Multimaps.index(badGuys.iterator(), stringLengthFunction);
1823       *   System.out.println(index);}</pre>
1824       *
1825       * prints <pre>   {@code
1826       *
1827       *   {4=[Inky], 6=[Blinky], 5=[Pinky, Pinky, Clyde]}}</pre>
1828       *
1829       * The returned multimap is serializable if its keys and values are all
1830       * serializable.
1831       *
1832       * @param values the values to use when constructing the {@code
1833       *     ImmutableListMultimap}
1834       * @param keyFunction the function used to produce the key for each value
1835       * @return {@code ImmutableListMultimap} mapping the result of evaluating the
1836       *     function {@code keyFunction} on each value in the input collection to
1837       *     that value
1838       * @throws NullPointerException if any of the following cases is true:
1839       *     <ul>
1840       *     <li>{@code values} is null
1841       *     <li>{@code keyFunction} is null
1842       *     <li>An element in {@code values} is null
1843       *     <li>{@code keyFunction} returns {@code null} for any element of {@code
1844       *         values}
1845       *     </ul>
1846       * @since 10.0
1847       */
1848      public static <K, V> ImmutableListMultimap<K, V> index(
1849          Iterator<V> values, Function<? super V, K> keyFunction) {
1850        checkNotNull(keyFunction);
1851        ImmutableListMultimap.Builder<K, V> builder
1852            = ImmutableListMultimap.builder();
1853        while (values.hasNext()) {
1854          V value = values.next();
1855          checkNotNull(value, values);
1856          builder.put(keyFunction.apply(value), value);
1857        }
1858        return builder.build();
1859      }
1860    
1861      static abstract class Keys<K, V> extends AbstractMultiset<K> {
1862        abstract Multimap<K, V> multimap();
1863    
1864        @Override Iterator<Multiset.Entry<K>> entryIterator() {
1865          final Iterator<Map.Entry<K, Collection<V>>> backingIterator =
1866              multimap().asMap().entrySet().iterator();
1867          return new Iterator<Multiset.Entry<K>>() {
1868            @Override public boolean hasNext() {
1869              return backingIterator.hasNext();
1870            }
1871    
1872            @Override public Multiset.Entry<K> next() {
1873              final Map.Entry<K, Collection<V>> backingEntry =
1874                  backingIterator.next();
1875              return new Multisets.AbstractEntry<K>() {
1876                @Override public K getElement() {
1877                  return backingEntry.getKey();
1878                }
1879    
1880                @Override public int getCount() {
1881                  return backingEntry.getValue().size();
1882                }
1883              };
1884            }
1885    
1886            @Override public void remove() {
1887              backingIterator.remove();
1888            }
1889          };
1890        }
1891    
1892        @Override int distinctElements() {
1893          return multimap().asMap().size();
1894        }
1895    
1896        @Override Set<Multiset.Entry<K>> createEntrySet() {
1897          return new KeysEntrySet();
1898        }
1899    
1900        class KeysEntrySet extends Multisets.EntrySet<K> {
1901          @Override Multiset<K> multiset() {
1902            return Keys.this;
1903          }
1904    
1905          @Override public Iterator<Multiset.Entry<K>> iterator() {
1906            return entryIterator();
1907          }
1908    
1909          @Override public int size() {
1910            return distinctElements();
1911          }
1912    
1913          @Override public boolean isEmpty() {
1914            return multimap().isEmpty();
1915          }
1916    
1917          @Override public boolean contains(@Nullable Object o) {
1918            if (o instanceof Multiset.Entry<?>) {
1919              Multiset.Entry<?> entry = (Multiset.Entry<?>) o;
1920              Collection<V> collection = multimap().asMap().get(entry.getElement());
1921              return collection != null && collection.size() == entry.getCount();
1922            }
1923            return false;
1924          }
1925    
1926          @Override public boolean remove(@Nullable Object o) {
1927            if (o instanceof Multiset.Entry<?>) {
1928              Multiset.Entry<?> entry = (Multiset.Entry<?>) o;
1929              Collection<V> collection = multimap().asMap().get(entry.getElement());
1930              if (collection != null && collection.size() == entry.getCount()) {
1931                collection.clear();
1932                return true;
1933              }
1934            }
1935            return false;
1936          }
1937        }
1938    
1939        @Override public boolean contains(@Nullable Object element) {
1940          return multimap().containsKey(element);
1941        }
1942    
1943        @Override public Iterator<K> iterator() {
1944          return Iterators.transform(multimap().entries().iterator(),
1945              new Function<Map.Entry<K, V>, K>() {
1946                @Override public K apply(Map.Entry<K, V> entry) {
1947                  return entry.getKey();
1948                }
1949              });
1950        }
1951    
1952        @Override public int count(@Nullable Object element) {
1953          try {
1954            if (multimap().containsKey(element)) {
1955              Collection<V> values = multimap().asMap().get(element);
1956              return (values == null) ? 0 : values.size();
1957            }
1958            return 0;
1959          } catch (ClassCastException e) {
1960            return 0;
1961          } catch (NullPointerException e) {
1962            return 0;
1963          }
1964        }
1965    
1966        @Override public int remove(@Nullable Object element, int occurrences) {
1967          checkArgument(occurrences >= 0);
1968          if (occurrences == 0) {
1969            return count(element);
1970          }
1971    
1972          Collection<V> values;
1973          try {
1974            values = multimap().asMap().get(element);
1975          } catch (ClassCastException e) {
1976            return 0;
1977          } catch (NullPointerException e) {
1978            return 0;
1979          }
1980    
1981          if (values == null) {
1982            return 0;
1983          }
1984    
1985          int oldCount = values.size();
1986          if (occurrences >= oldCount) {
1987            values.clear();
1988          } else {
1989            Iterator<V> iterator = values.iterator();
1990            for (int i = 0; i < occurrences; i++) {
1991              iterator.next();
1992              iterator.remove();
1993            }
1994          }
1995          return oldCount;
1996        }
1997    
1998        @Override public void clear() {
1999          multimap().clear();
2000        }
2001    
2002        @Override public Set<K> elementSet() {
2003          return multimap().keySet();
2004        }
2005      }
2006    
2007      static abstract class Values<K, V> extends AbstractCollection<V> {
2008        abstract Multimap<K, V> multimap();
2009    
2010        @Override public Iterator<V> iterator() {
2011          final Iterator<Map.Entry<K, V>> backingIterator =
2012              multimap().entries().iterator();
2013          return new Iterator<V>() {
2014            @Override public boolean hasNext() {
2015              return backingIterator.hasNext();
2016            }
2017    
2018            @Override public V next() {
2019              return backingIterator.next().getValue();
2020            }
2021    
2022            @Override public void remove() {
2023              backingIterator.remove();
2024            }
2025          };
2026        }
2027    
2028        @Override public int size() {
2029          return multimap().size();
2030        }
2031    
2032        @Override public boolean contains(@Nullable Object o) {
2033          return multimap().containsValue(o);
2034        }
2035    
2036        @Override public void clear() {
2037          multimap().clear();
2038        }
2039      }
2040    
2041      /**
2042       * A skeleton implementation of {@link Multimap#entries()}.
2043       */
2044      static abstract class Entries<K, V> extends
2045          AbstractCollection<Map.Entry<K, V>> {
2046        abstract Multimap<K, V> multimap();
2047    
2048        @Override public int size() {
2049          return multimap().size();
2050        }
2051    
2052        @Override public boolean contains(@Nullable Object o) {
2053          if (o instanceof Map.Entry<?, ?>) {
2054            Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
2055            return multimap().containsEntry(entry.getKey(), entry.getValue());
2056          }
2057          return false;
2058        }
2059    
2060        @Override public boolean remove(@Nullable Object o) {
2061          if (o instanceof Map.Entry<?, ?>) {
2062            Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
2063            return multimap().remove(entry.getKey(), entry.getValue());
2064          }
2065          return false;
2066        }
2067    
2068        @Override public void clear() {
2069          multimap().clear();
2070        }
2071      }
2072    
2073      /**
2074       * A skeleton implementation of {@link SetMultimap#entries()}.
2075       */
2076      static abstract class EntrySet<K, V> extends Entries<K, V> implements
2077          Set<Map.Entry<K, V>> {
2078        @Override public int hashCode() {
2079          return Sets.hashCodeImpl(this);
2080        }
2081    
2082        @Override public boolean equals(@Nullable Object obj) {
2083          return Sets.equalsImpl(this, obj);
2084        }
2085      }
2086    
2087      /**
2088       * A skeleton implementation of {@link Multimap#asMap()}.
2089       */
2090      static abstract class AsMap<K, V> extends
2091          Maps.ImprovedAbstractMap<K, Collection<V>> {
2092        abstract Multimap<K, V> multimap();
2093    
2094        @Override public abstract int size();
2095    
2096        abstract Iterator<Entry<K, Collection<V>>> entryIterator();
2097    
2098        @Override protected Set<Entry<K, Collection<V>>> createEntrySet() {
2099          return new EntrySet();
2100        }
2101    
2102        void removeValuesForKey(Object key){
2103          multimap().removeAll(key);
2104        }
2105    
2106        class EntrySet extends Maps.EntrySet<K, Collection<V>> {
2107          @Override Map<K, Collection<V>> map() {
2108            return AsMap.this;
2109          }
2110    
2111          @Override public Iterator<Entry<K, Collection<V>>> iterator() {
2112            return entryIterator();
2113          }
2114    
2115          @Override public boolean remove(Object o) {
2116            if (!contains(o)) {
2117              return false;
2118            }
2119            Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
2120            removeValuesForKey(entry.getKey());
2121            return true;
2122          }
2123        }
2124    
2125        @SuppressWarnings("unchecked")
2126        @Override public Collection<V> get(Object key) {
2127          return containsKey(key) ? multimap().get((K) key) : null;
2128        }
2129    
2130        @Override public Collection<V> remove(Object key) {
2131          return containsKey(key) ? multimap().removeAll(key) : null;
2132        }
2133    
2134        @Override public Set<K> keySet() {
2135          return multimap().keySet();
2136        }
2137    
2138        @Override public boolean isEmpty() {
2139          return multimap().isEmpty();
2140        }
2141    
2142        @Override public boolean containsKey(Object key) {
2143          return multimap().containsKey(key);
2144        }
2145    
2146        @Override public void clear() {
2147          multimap().clear();
2148        }
2149      }
2150    
2151      /**
2152       * Returns a multimap containing the mappings in {@code unfiltered} whose keys
2153       * satisfy a predicate. The returned multimap is a live view of
2154       * {@code unfiltered}; changes to one affect the other.
2155       *
2156       * <p>The resulting multimap's views have iterators that don't support
2157       * {@code remove()}, but all other methods are supported by the multimap and
2158       * its views. When adding a key that doesn't satisfy the predicate, the
2159       * multimap's {@code put()}, {@code putAll()}, and {@replaceValues()} methods
2160       * throw an {@link IllegalArgumentException}.
2161       *
2162       * <p>When methods such as {@code removeAll()} and {@code clear()} are called on
2163       * the filtered multimap or its views, only mappings whose keys satisfy the
2164       * filter will be removed from the underlying multimap.
2165       *
2166       * <p>The returned multimap isn't threadsafe or serializable, even if
2167       * {@code unfiltered} is.
2168       *
2169       * <p>Many of the filtered multimap's methods, such as {@code size()}, iterate
2170       * across every key/value mapping in the underlying multimap and determine
2171       * which satisfy the filter. When a live view is <i>not</i> needed, it may be
2172       * faster to copy the filtered multimap and use the copy.
2173       *
2174       * <p><b>Warning:</b> {@code keyPredicate} must be <i>consistent with equals</i>,
2175       * as documented at {@link Predicate#apply}. Do not provide a predicate such
2176       * as {@code Predicates.instanceOf(ArrayList.class)}, which is inconsistent
2177       * with equals.
2178       *
2179       * @since 11.0
2180       */
2181      @Beta
2182      @GwtIncompatible(value = "untested")
2183      public static <K, V> Multimap<K, V> filterKeys(
2184        Multimap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
2185        checkNotNull(keyPredicate);
2186        Predicate<Entry<K, V>> entryPredicate =
2187            new Predicate<Entry<K, V>>() {
2188              @Override
2189              public boolean apply(Entry<K, V> input) {
2190                return keyPredicate.apply(input.getKey());
2191              }
2192            };
2193        return filterEntries(unfiltered, entryPredicate);
2194      }
2195    
2196      /**
2197       * Returns a multimap containing the mappings in {@code unfiltered} whose values
2198       * satisfy a predicate. The returned multimap is a live view of
2199       * {@code unfiltered}; changes to one affect the other.
2200       *
2201       * <p>The resulting multimap's views have iterators that don't support
2202       * {@code remove()}, but all other methods are supported by the multimap and
2203       * its views. When adding a value that doesn't satisfy the predicate, the
2204       * multimap's {@code put()}, {@code putAll()}, and {@replaceValues()} methods
2205       * throw an {@link IllegalArgumentException}.
2206       *
2207       * <p>When methods such as {@code removeAll()} and {@code clear()} are called on
2208       * the filtered multimap or its views, only mappings whose value satisfy the
2209       * filter will be removed from the underlying multimap.
2210       *
2211       * <p>The returned multimap isn't threadsafe or serializable, even if
2212       * {@code unfiltered} is.
2213       *
2214       * <p>Many of the filtered multimap's methods, such as {@code size()}, iterate
2215       * across every key/value mapping in the underlying multimap and determine
2216       * which satisfy the filter. When a live view is <i>not</i> needed, it may be
2217       * faster to copy the filtered multimap and use the copy.
2218       *
2219       * <p><b>Warning:</b> {@code valuePredicate} must be <i>consistent with
2220       * equals</i>, as documented at {@link Predicate#apply}. Do not provide a
2221       * predicate such as {@code Predicates.instanceOf(ArrayList.class)}, which is
2222       * inconsistent with equals.
2223       *
2224       * @since 11.0
2225       */
2226      @Beta
2227      @GwtIncompatible(value = "untested")
2228      public static <K, V> Multimap<K, V> filterValues(
2229        Multimap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
2230        checkNotNull(valuePredicate);
2231        Predicate<Entry<K, V>> entryPredicate =
2232            new Predicate<Entry<K, V>>() {
2233              @Override
2234              public boolean apply(Entry<K, V> input) {
2235                return valuePredicate.apply(input.getValue());
2236              }
2237            };
2238        return filterEntries(unfiltered, entryPredicate);
2239      }
2240    
2241      /**
2242       * Returns a multimap containing the mappings in {@code unfiltered} that
2243       * satisfy a predicate. The returned multimap is a live view of
2244       * {@code unfiltered}; changes to one affect the other.
2245       *
2246       * <p>The resulting multimap's views have iterators that don't support
2247       * {@code remove()}, but all other methods are supported by the multimap and
2248       * its views. When adding a key/value pair that doesn't satisfy the predicate,
2249       * multimap's {@code put()}, {@code putAll()}, and {@replaceValues()} methods
2250       * throw an {@link IllegalArgumentException}.
2251       *
2252       * <p>When methods such as {@code removeAll()} and {@code clear()} are called on
2253       * the filtered multimap or its views, only mappings whose keys satisfy the
2254       * filter will be removed from the underlying multimap.
2255       *
2256       * <p>The returned multimap isn't threadsafe or serializable, even if
2257       * {@code unfiltered} is.
2258       *
2259       * <p>Many of the filtered multimap's methods, such as {@code size()}, iterate
2260       * across every key/value mapping in the underlying multimap and determine
2261       * which satisfy the filter. When a live view is <i>not</i> needed, it may be
2262       * faster to copy the filtered multimap and use the copy.
2263       *
2264       * <p><b>Warning:</b> {@code entryPredicate} must be <i>consistent with
2265       * equals</i>, as documented at {@link Predicate#apply}.
2266       *
2267       * @since 11.0
2268       */
2269      @Beta
2270      @GwtIncompatible(value = "untested")
2271      public static <K, V> Multimap<K, V> filterEntries(
2272        Multimap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
2273        checkNotNull(entryPredicate);
2274        return (unfiltered instanceof FilteredMultimap)
2275            ? filterFiltered((FilteredMultimap<K, V>) unfiltered, entryPredicate)
2276            : new FilteredMultimap<K, V>(checkNotNull(unfiltered), entryPredicate);
2277      }
2278    
2279      /**
2280       * Support removal operations when filtering a filtered multimap. Since a
2281       * filtered multimap has iterators that don't support remove, passing one to
2282       * the FilteredMultimap constructor would lead to a multimap whose removal
2283       * operations would fail. This method combines the predicates to avoid that
2284       * problem.
2285       */
2286      private static <K, V> Multimap<K, V> filterFiltered(FilteredMultimap<K, V> map,
2287          Predicate<? super Entry<K, V>> entryPredicate) {
2288        Predicate<Entry<K, V>> predicate
2289            = Predicates.and(map.predicate, entryPredicate);
2290        return new FilteredMultimap<K, V>(map.unfiltered, predicate);
2291      }
2292    
2293      private static class FilteredMultimap<K, V> implements Multimap<K, V> {
2294        final Multimap<K, V> unfiltered;
2295        final Predicate<? super Entry<K, V>> predicate;
2296    
2297        FilteredMultimap(Multimap<K, V> unfiltered, Predicate<? super Entry<K, V>> predicate) {
2298          this.unfiltered = unfiltered;
2299          this.predicate = predicate;
2300        }
2301    
2302        @Override public int size() {
2303          return entries().size();
2304        }
2305    
2306        @Override public boolean isEmpty() {
2307          return entries().isEmpty();
2308        }
2309    
2310        @Override public boolean containsKey(Object key) {
2311          return asMap().containsKey(key);
2312        }
2313    
2314        @Override public boolean containsValue(Object value) {
2315          return values().contains(value);
2316        }
2317    
2318        // This method should be called only when key is a K and value is a V.
2319        @SuppressWarnings("unchecked")
2320        boolean satisfiesPredicate(Object key, Object value) {
2321          return predicate.apply(Maps.immutableEntry((K) key, (V) value));
2322        }
2323    
2324        @Override public boolean containsEntry(Object key, Object value) {
2325          return unfiltered.containsEntry(key, value) && satisfiesPredicate(key, value);
2326        }
2327    
2328        @Override public boolean put(K key, V value) {
2329          checkArgument(satisfiesPredicate(key, value));
2330          return unfiltered.put(key, value);
2331        }
2332    
2333        @Override public boolean remove(Object key, Object value) {
2334          return containsEntry(key, value) ? unfiltered.remove(key, value) : false;
2335        }
2336    
2337        @Override public boolean putAll(K key, Iterable<? extends V> values) {
2338          for (V value : values) {
2339            checkArgument(satisfiesPredicate(key, value));
2340          }
2341          return unfiltered.putAll(key, values);
2342        }
2343    
2344        @Override public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
2345          for (Entry<? extends K, ? extends V> entry : multimap.entries()) {
2346            checkArgument(satisfiesPredicate(entry.getKey(), entry.getValue()));
2347          }
2348          return unfiltered.putAll(multimap);
2349        }
2350    
2351        @Override public Collection<V> replaceValues(K key, Iterable<? extends V> values) {
2352          for (V value : values) {
2353            checkArgument(satisfiesPredicate(key, value));
2354          }
2355          // Not calling unfiltered.replaceValues() since values that don't satisify
2356          // the filter should remain in the multimap.
2357          Collection<V> oldValues = removeAll(key);
2358          unfiltered.putAll(key, values);
2359          return oldValues;
2360        }
2361    
2362        @Override public Collection<V> removeAll(Object key) {
2363          List<V> removed = Lists.newArrayList();
2364          Collection<V> values = unfiltered.asMap().get(key);
2365          if (values != null) {
2366            Iterator<V> iterator = values.iterator();
2367            while (iterator.hasNext()) {
2368              V value = iterator.next();
2369              if (satisfiesPredicate(key, value)) {
2370                removed.add(value);
2371                iterator.remove();
2372              }
2373            }
2374          }
2375          if (unfiltered instanceof SetMultimap) {
2376            return Collections.unmodifiableSet(Sets.newLinkedHashSet(removed));
2377          } else {
2378            return Collections.unmodifiableList(removed);
2379          }
2380        }
2381    
2382        @Override public void clear() {
2383          entries().clear();
2384        }
2385    
2386        @Override public boolean equals(@Nullable Object object) {
2387          if (object == this) {
2388            return true;
2389          }
2390          if (object instanceof Multimap) {
2391            Multimap<?, ?> that = (Multimap<?, ?>) object;
2392            return asMap().equals(that.asMap());
2393          }
2394          return false;
2395        }
2396    
2397        @Override public int hashCode() {
2398          return asMap().hashCode();
2399        }
2400    
2401        @Override public String toString() {
2402          return asMap().toString();
2403        }
2404    
2405        class ValuePredicate implements Predicate<V> {
2406          final K key;
2407          ValuePredicate(K key) {
2408            this.key = key;
2409          }
2410          @Override public boolean apply(V value) {
2411            return satisfiesPredicate(key, value);
2412          }
2413        }
2414    
2415        Collection<V> filterCollection(Collection<V> collection, Predicate<V> predicate) {
2416          if (collection instanceof Set) {
2417            return Sets.filter((Set<V>) collection, predicate);
2418          } else {
2419            return Collections2.filter(collection, predicate);
2420          }
2421        }
2422    
2423        @Override public Collection<V> get(K key) {
2424          return filterCollection(unfiltered.get(key), new ValuePredicate(key));
2425        }
2426    
2427        @Override public Set<K> keySet() {
2428          return asMap().keySet();
2429        }
2430    
2431        Collection<V> values;
2432    
2433        @Override public Collection<V> values() {
2434          return (values == null) ? values = new Values() : values;
2435        }
2436    
2437        class Values extends Multimaps.Values<K, V> {
2438          @Override Multimap<K, V> multimap() {
2439            return FilteredMultimap.this;
2440          }
2441    
2442          @Override public boolean contains(@Nullable Object o) {
2443            return Iterators.contains(iterator(), o);
2444          }
2445    
2446          // Override remove methods since iterator doesn't support remove.
2447    
2448          @Override public boolean remove(Object o) {
2449            Iterator<Entry<K, V>> iterator = unfiltered.entries().iterator();
2450            while (iterator.hasNext()) {
2451              Entry<K, V> entry = iterator.next();
2452              if (Objects.equal(o, entry.getValue()) && predicate.apply(entry)) {
2453                iterator.remove();
2454                return true;
2455              }
2456            }
2457            return false;
2458          }
2459    
2460          @Override public boolean removeAll(Collection<?> c) {
2461            boolean changed = false;
2462            Iterator<Entry<K, V>> iterator = unfiltered.entries().iterator();
2463            while (iterator.hasNext()) {
2464              Entry<K, V> entry = iterator.next();
2465              if (c.contains(entry.getValue()) && predicate.apply(entry)) {
2466                iterator.remove();
2467                changed = true;
2468              }
2469            }
2470            return changed;
2471          }
2472    
2473          @Override public boolean retainAll(Collection<?> c) {
2474            boolean changed = false;
2475            Iterator<Entry<K, V>> iterator = unfiltered.entries().iterator();
2476            while (iterator.hasNext()) {
2477              Entry<K, V> entry = iterator.next();
2478              if (!c.contains(entry.getValue()) && predicate.apply(entry)) {
2479                iterator.remove();
2480                changed = true;
2481              }
2482            }
2483            return changed;
2484          }
2485        }
2486    
2487        Collection<Entry<K, V>> entries;
2488    
2489        @Override public Collection<Entry<K, V>> entries() {
2490          return (entries == null)
2491              ? entries = Collections2.filter(unfiltered.entries(), predicate)
2492              : entries;
2493        }
2494    
2495        /**
2496         * Remove all filtered asMap() entries that satisfy the predicate.
2497         */
2498        boolean removeEntriesIf(Predicate<Map.Entry<K, Collection<V>>> removalPredicate) {
2499          Iterator<Map.Entry<K, Collection<V>>> iterator = unfiltered.asMap().entrySet().iterator();
2500          boolean changed = false;
2501          while (iterator.hasNext()) {
2502            // Determine whether to remove the filtered values with this key.
2503            Map.Entry<K, Collection<V>> entry = iterator.next();
2504            K key = entry.getKey();
2505            Collection<V> collection = entry.getValue();
2506            Predicate<V> valuePredicate = new ValuePredicate(key);
2507            Collection<V> filteredCollection = filterCollection(collection, valuePredicate);
2508            Map.Entry<K, Collection<V>> filteredEntry = Maps.immutableEntry(key, filteredCollection);
2509            if (removalPredicate.apply(filteredEntry) && !filteredCollection.isEmpty()) {
2510              changed = true;
2511              if (Iterables.all(collection, valuePredicate)) {
2512                iterator.remove();  // Remove all values for the key.
2513              } else {
2514                filteredCollection.clear();  // Remove the filtered values only.
2515              }
2516            }
2517          }
2518          return changed;
2519        }
2520    
2521        Map<K, Collection<V>> asMap;
2522    
2523        @Override public Map<K, Collection<V>> asMap() {
2524          return (asMap == null) ? asMap = createAsMap() : asMap;
2525        }
2526    
2527        static final Predicate<Collection<?>> NOT_EMPTY = new Predicate<Collection<?>>() {
2528          @Override public boolean apply(Collection<?> input) {
2529            return !input.isEmpty();
2530          }
2531        };
2532    
2533        Map<K, Collection<V>> createAsMap() {
2534          // Select the values that satisify the predicate.
2535          EntryTransformer<K, Collection<V>, Collection<V>> transformer
2536              = new EntryTransformer<K, Collection<V>, Collection<V>>() {
2537                @Override public Collection<V> transformEntry(K key, Collection<V> collection) {
2538                  return filterCollection(collection, new ValuePredicate(key));
2539                }
2540          };
2541          Map<K, Collection<V>> transformed
2542              = Maps.transformEntries(unfiltered.asMap(), transformer);
2543    
2544          // Select the keys that have at least one value remaining.
2545          Map<K, Collection<V>> filtered = Maps.filterValues(transformed, NOT_EMPTY);
2546    
2547          // Override the removal methods, since removing a map entry should not
2548          // affect values that don't satisfy the filter.
2549          return new AsMap(filtered);
2550        }
2551    
2552        class AsMap extends ForwardingMap<K, Collection<V>> {
2553         final Map<K, Collection<V>> delegate;
2554    
2555          AsMap(Map<K, Collection<V>> delegate) {
2556            this.delegate = delegate;
2557          }
2558    
2559          @Override protected Map<K, Collection<V>> delegate() {
2560            return delegate;
2561          }
2562    
2563          @Override public Collection<V> remove(Object o) {
2564            Collection<V> output = FilteredMultimap.this.removeAll(o);
2565            return output.isEmpty() ? null : output;
2566          }
2567    
2568          @Override public void clear() {
2569            FilteredMultimap.this.clear();
2570          }
2571    
2572          Set<K> keySet;
2573    
2574          @Override public Set<K> keySet() {
2575            return (keySet == null) ? keySet = new KeySet() : keySet;
2576          }
2577    
2578          class KeySet extends Maps.KeySet<K, Collection<V>> {
2579            @Override Map<K, Collection<V>> map() {
2580              return AsMap.this;
2581            }
2582    
2583            @Override public boolean remove(Object o) {
2584               Collection<V> collection = delegate.get(o);
2585               if (collection == null) {
2586                 return false;
2587               }
2588               collection.clear();
2589               return true;
2590            }
2591    
2592            @Override public boolean removeAll(Collection<?> c) {
2593              return Sets.removeAllImpl(this, c);
2594            }
2595    
2596            @Override public boolean retainAll(final Collection<?> c) {
2597              Predicate<Map.Entry<K, Collection<V>>> removalPredicate
2598                  = new Predicate<Map.Entry<K, Collection<V>>>() {
2599                    @Override public boolean apply(Map.Entry<K, Collection<V>> entry) {
2600                      return !c.contains(entry.getKey());
2601                    }
2602                  };
2603              return removeEntriesIf(removalPredicate);
2604            }
2605          }
2606    
2607          Values asMapValues;
2608    
2609          @Override public Collection<Collection<V>> values() {
2610            return (asMapValues == null) ? asMapValues = new Values() : asMapValues;
2611          }
2612    
2613          class Values extends Maps.Values<K, Collection<V>> {
2614            @Override Map<K, Collection<V>> map() {
2615              return AsMap.this;
2616            }
2617    
2618            @Override public boolean remove(Object o) {
2619              for (Collection<V> collection : this) {
2620                if (collection.equals(o)) {
2621                  collection.clear();
2622                  return true;
2623                }
2624              }
2625              return false;
2626            }
2627    
2628            @Override public boolean removeAll(final Collection<?> c) {
2629              Predicate<Map.Entry<K, Collection<V>>> removalPredicate
2630                  = new Predicate<Map.Entry<K, Collection<V>>>() {
2631                    @Override public boolean apply(Map.Entry<K, Collection<V>> entry) {
2632                      return c.contains(entry.getValue());
2633                    }
2634                  };
2635              return removeEntriesIf(removalPredicate);
2636            }
2637    
2638            @Override public boolean retainAll(final Collection<?> c) {
2639              Predicate<Map.Entry<K, Collection<V>>> removalPredicate
2640                  = new Predicate<Map.Entry<K, Collection<V>>>() {
2641                    @Override public boolean apply(Map.Entry<K, Collection<V>> entry) {
2642                      return !c.contains(entry.getValue());
2643                    }
2644                  };
2645              return removeEntriesIf(removalPredicate);
2646            }
2647          }
2648    
2649          EntrySet entrySet;
2650    
2651          @Override public Set<Map.Entry<K, Collection<V>>> entrySet() {
2652            return (entrySet == null) ? entrySet = new EntrySet(super.entrySet()) : entrySet;
2653          }
2654    
2655          class EntrySet extends Maps.EntrySet<K, Collection<V>> {
2656            Set<Map.Entry<K, Collection<V>>> delegateEntries;
2657    
2658            public EntrySet(Set<Map.Entry<K, Collection<V>>> delegateEntries) {
2659              this.delegateEntries = delegateEntries;
2660            }
2661    
2662            @Override Map<K, Collection<V>> map() {
2663              return AsMap.this;
2664            }
2665    
2666            @Override public Iterator<Map.Entry<K, Collection<V>>> iterator() {
2667              return delegateEntries.iterator();
2668            }
2669    
2670            @Override public boolean remove(Object o) {
2671              if (o instanceof Entry<?, ?>) {
2672                Entry<?, ?> entry = (Entry<?, ?>) o;
2673                Collection<V> collection = delegate.get(entry.getKey());
2674                if (collection != null && collection.equals(entry.getValue())) {
2675                  collection.clear();
2676                  return true;
2677                }
2678              }
2679              return false;
2680            }
2681    
2682            @Override public boolean removeAll(Collection<?> c) {
2683              return Sets.removeAllImpl(this, c);
2684            }
2685    
2686            @Override public boolean retainAll(final Collection<?> c) {
2687              Predicate<Map.Entry<K, Collection<V>>> removalPredicate
2688                  = new Predicate<Map.Entry<K, Collection<V>>>() {
2689                    @Override public boolean apply(Map.Entry<K, Collection<V>> entry) {
2690                      return !c.contains(entry);
2691                    }
2692                  };
2693              return removeEntriesIf(removalPredicate);
2694            }
2695          }
2696        }
2697    
2698        AbstractMultiset<K> keys;
2699    
2700        @Override public Multiset<K> keys() {
2701          return (keys == null) ? keys = new Keys() : keys;
2702        }
2703    
2704        class Keys extends Multimaps.Keys<K, V> {
2705          @Override Multimap<K, V> multimap() {
2706            return FilteredMultimap.this;
2707          }
2708    
2709          @Override public int remove(Object o, int occurrences) {
2710            checkArgument(occurrences >= 0);
2711            Collection<V> values = unfiltered.asMap().get(o);
2712            if (values == null) {
2713              return 0;
2714            }
2715            int priorCount = 0;
2716            int removed = 0;
2717            Iterator<V> iterator = values.iterator();
2718            while (iterator.hasNext()) {
2719              if (satisfiesPredicate(o, iterator.next())) {
2720                priorCount++;
2721                if (removed < occurrences) {
2722                  iterator.remove();
2723                  removed++;
2724                }
2725              }
2726            }
2727            return priorCount;
2728          }
2729    
2730          @Override Set<Multiset.Entry<K>> createEntrySet() {
2731            return new EntrySet();
2732          }
2733    
2734          class EntrySet extends Multimaps.Keys<K, V>.KeysEntrySet {
2735            @Override public boolean removeAll(Collection<?> c) {
2736              return Sets.removeAllImpl(this, c);
2737            }
2738    
2739            @Override public boolean retainAll(final Collection<?> c) {
2740              Predicate<Map.Entry<K, Collection<V>>> removalPredicate
2741                  = new Predicate<Map.Entry<K, Collection<V>>>() {
2742                    @Override public boolean apply(Map.Entry<K, Collection<V>> entry) {
2743                      Multiset.Entry<K> multisetEntry
2744                          = Multisets.immutableEntry(entry.getKey(), entry.getValue().size());
2745                      return !c.contains(multisetEntry);
2746                    }
2747                  };
2748              return removeEntriesIf(removalPredicate);
2749            }
2750          }
2751        }
2752      }
2753    
2754      // TODO(jlevy): Create methods that filter a SetMultimap or SortedSetMultimap.
2755    }