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