001 /*
002 * Copyright (C) 2007 Google Inc.
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.checkNotNull;
020 import static com.google.common.base.Preconditions.checkState;
021
022 import com.google.common.annotations.Beta;
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.Supplier;
029 import com.google.common.collect.Collections2.TransformedCollection;
030 import com.google.common.collect.Maps.EntryTransformer;
031
032 import java.io.IOException;
033 import java.io.ObjectInputStream;
034 import java.io.ObjectOutputStream;
035 import java.io.Serializable;
036 import java.util.AbstractSet;
037 import java.util.Collection;
038 import java.util.Collections;
039 import java.util.Comparator;
040 import java.util.HashSet;
041 import java.util.Iterator;
042 import java.util.List;
043 import java.util.Map;
044 import java.util.Map.Entry;
045 import java.util.NoSuchElementException;
046 import java.util.Set;
047 import java.util.SortedSet;
048
049 import javax.annotation.Nullable;
050
051 /**
052 * Provides static methods acting on or generating a {@code Multimap}.
053 *
054 * @author Jared Levy
055 * @author Robert Konigsberg
056 * @author Mike Bostock
057 * @author Louis Wasserman
058 * @since 2 (imported from Google Collections Library)
059 */
060 @GwtCompatible(emulated = true)
061 public final class Multimaps {
062 private Multimaps() {}
063
064 /**
065 * Creates a new {@code Multimap} that uses the provided map and factory. It
066 * can generate a multimap based on arbitrary {@link Map} and
067 * {@link Collection} classes.
068 *
069 * <p>The {@code factory}-generated and {@code map} classes determine the
070 * multimap iteration order. They also specify the behavior of the
071 * {@code equals}, {@code hashCode}, and {@code toString} methods for the
072 * multimap and its returned views. However, the multimap's {@code get}
073 * method returns instances of a different class than {@code factory.get()}
074 * does.
075 *
076 * <p>The multimap is serializable if {@code map}, {@code factory}, the
077 * collections generated by {@code factory}, and the multimap contents are all
078 * serializable.
079 *
080 * <p>The multimap is not threadsafe when any concurrent operations update the
081 * multimap, even if {@code map} and the instances generated by
082 * {@code factory} are. Concurrent read operations will work correctly. To
083 * allow concurrent update operations, wrap the multimap with a call to
084 * {@link #synchronizedMultimap}.
085 *
086 * <p>Call this method only when the simpler methods
087 * {@link ArrayListMultimap#create()}, {@link HashMultimap#create()},
088 * {@link LinkedHashMultimap#create()}, {@link LinkedListMultimap#create()},
089 * {@link TreeMultimap#create()}, and
090 * {@link TreeMultimap#create(Comparator, Comparator)} won't suffice.
091 *
092 * <p>Note: the multimap assumes complete ownership over of {@code map} and
093 * the collections returned by {@code factory}. Those objects should not be
094 * manually updated and they should not use soft, weak, or phantom references.
095 *
096 * @param map place to store the mapping from each key to its corresponding
097 * values
098 * @param factory supplier of new, empty collections that will each hold all
099 * values for a given key
100 * @throws IllegalArgumentException if {@code map} is not empty
101 */
102 public static <K, V> Multimap<K, V> newMultimap(Map<K, Collection<V>> map,
103 final Supplier<? extends Collection<V>> factory) {
104 return new CustomMultimap<K, V>(map, factory);
105 }
106
107 private static class CustomMultimap<K, V> extends AbstractMultimap<K, V> {
108 transient Supplier<? extends Collection<V>> factory;
109
110 CustomMultimap(Map<K, Collection<V>> map,
111 Supplier<? extends Collection<V>> factory) {
112 super(map);
113 this.factory = checkNotNull(factory);
114 }
115
116 @Override protected Collection<V> createCollection() {
117 return factory.get();
118 }
119
120 // can't use Serialization writeMultimap and populateMultimap methods since
121 // there's no way to generate the empty backing map.
122
123 /** @serialData the factory and the backing map */
124 @GwtIncompatible("java.io.ObjectOutputStream")
125 private void writeObject(ObjectOutputStream stream) throws IOException {
126 stream.defaultWriteObject();
127 stream.writeObject(factory);
128 stream.writeObject(backingMap());
129 }
130
131 @GwtIncompatible("java.io.ObjectInputStream")
132 @SuppressWarnings("unchecked") // reading data stored by writeObject
133 private void readObject(ObjectInputStream stream)
134 throws IOException, ClassNotFoundException {
135 stream.defaultReadObject();
136 factory = (Supplier<? extends Collection<V>>) stream.readObject();
137 Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject();
138 setMap(map);
139 }
140
141 @GwtIncompatible("java serialization not supported")
142 private static final long serialVersionUID = 0;
143 }
144
145 /**
146 * Creates a new {@code ListMultimap} that uses the provided map and factory.
147 * It can generate a multimap based on arbitrary {@link Map} and {@link List}
148 * classes.
149 *
150 * <p>The {@code factory}-generated and {@code map} classes determine the
151 * multimap iteration order. They also specify the behavior of the
152 * {@code equals}, {@code hashCode}, and {@code toString} methods for the
153 * multimap and its returned views. The multimap's {@code get}, {@code
154 * removeAll}, and {@code replaceValues} methods return {@code RandomAccess}
155 * lists if the factory does. However, the multimap's {@code get} method
156 * returns instances of a different class than does {@code factory.get()}.
157 *
158 * <p>The multimap is serializable if {@code map}, {@code factory}, the
159 * lists generated by {@code factory}, and the multimap contents are all
160 * serializable.
161 *
162 * <p>The multimap is not threadsafe when any concurrent operations update the
163 * multimap, even if {@code map} and the instances generated by
164 * {@code factory} are. Concurrent read operations will work correctly. To
165 * allow concurrent update operations, wrap the multimap with a call to
166 * {@link #synchronizedListMultimap}.
167 *
168 * <p>Call this method only when the simpler methods
169 * {@link ArrayListMultimap#create()} and {@link LinkedListMultimap#create()}
170 * won't suffice.
171 *
172 * <p>Note: the multimap assumes complete ownership over of {@code map} and
173 * the lists returned by {@code factory}. Those objects should not be manually
174 * updated and they should not use soft, weak, or phantom references.
175 *
176 * @param map place to store the mapping from each key to its corresponding
177 * values
178 * @param factory supplier of new, empty lists that will each hold all values
179 * for a given key
180 * @throws IllegalArgumentException if {@code map} is not empty
181 */
182 public static <K, V> ListMultimap<K, V> newListMultimap(
183 Map<K, Collection<V>> map, final Supplier<? extends List<V>> factory) {
184 return new CustomListMultimap<K, V>(map, factory);
185 }
186
187 private static class CustomListMultimap<K, V>
188 extends AbstractListMultimap<K, V> {
189 transient Supplier<? extends List<V>> factory;
190
191 CustomListMultimap(Map<K, Collection<V>> map,
192 Supplier<? extends List<V>> factory) {
193 super(map);
194 this.factory = checkNotNull(factory);
195 }
196
197 @Override protected List<V> createCollection() {
198 return factory.get();
199 }
200
201 /** @serialData the factory and the backing map */
202 @GwtIncompatible("java.io.ObjectOutputStream")
203 private void writeObject(ObjectOutputStream stream) throws IOException {
204 stream.defaultWriteObject();
205 stream.writeObject(factory);
206 stream.writeObject(backingMap());
207 }
208
209 @GwtIncompatible("java.io.ObjectInputStream")
210 @SuppressWarnings("unchecked") // reading data stored by writeObject
211 private void readObject(ObjectInputStream stream)
212 throws IOException, ClassNotFoundException {
213 stream.defaultReadObject();
214 factory = (Supplier<? extends List<V>>) stream.readObject();
215 Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject();
216 setMap(map);
217 }
218
219 @GwtIncompatible("java serialization not supported")
220 private static final long serialVersionUID = 0;
221 }
222
223 /**
224 * Creates a new {@code SetMultimap} that uses the provided map and factory.
225 * It can generate a multimap based on arbitrary {@link Map} and {@link Set}
226 * classes.
227 *
228 * <p>The {@code factory}-generated and {@code map} classes determine the
229 * multimap iteration order. They also specify the behavior of the
230 * {@code equals}, {@code hashCode}, and {@code toString} methods for the
231 * multimap and its returned views. However, the multimap's {@code get}
232 * method returns instances of a different class than {@code factory.get()}
233 * does.
234 *
235 * <p>The multimap is serializable if {@code map}, {@code factory}, the
236 * sets generated by {@code factory}, and the multimap contents are all
237 * serializable.
238 *
239 * <p>The multimap is not threadsafe when any concurrent operations update the
240 * multimap, even if {@code map} and the instances generated by
241 * {@code factory} are. Concurrent read operations will work correctly. To
242 * allow concurrent update operations, wrap the multimap with a call to
243 * {@link #synchronizedSetMultimap}.
244 *
245 * <p>Call this method only when the simpler methods
246 * {@link HashMultimap#create()}, {@link LinkedHashMultimap#create()},
247 * {@link TreeMultimap#create()}, and
248 * {@link TreeMultimap#create(Comparator, Comparator)} won't suffice.
249 *
250 * <p>Note: the multimap assumes complete ownership over of {@code map} and
251 * the sets returned by {@code factory}. Those objects should not be manually
252 * updated and they should not use soft, weak, or phantom references.
253 *
254 * @param map place to store the mapping from each key to its corresponding
255 * values
256 * @param factory supplier of new, empty sets that will each hold all values
257 * for a given key
258 * @throws IllegalArgumentException if {@code map} is not empty
259 */
260 public static <K, V> SetMultimap<K, V> newSetMultimap(
261 Map<K, Collection<V>> map, final Supplier<? extends Set<V>> factory) {
262 return new CustomSetMultimap<K, V>(map, factory);
263 }
264
265 private static class CustomSetMultimap<K, V>
266 extends AbstractSetMultimap<K, V> {
267 transient Supplier<? extends Set<V>> factory;
268
269 CustomSetMultimap(Map<K, Collection<V>> map,
270 Supplier<? extends Set<V>> factory) {
271 super(map);
272 this.factory = checkNotNull(factory);
273 }
274
275 @Override protected Set<V> createCollection() {
276 return factory.get();
277 }
278
279 /** @serialData the factory and the backing map */
280 @GwtIncompatible("java.io.ObjectOutputStream")
281 private void writeObject(ObjectOutputStream stream) throws IOException {
282 stream.defaultWriteObject();
283 stream.writeObject(factory);
284 stream.writeObject(backingMap());
285 }
286
287 @GwtIncompatible("java.io.ObjectInputStream")
288 @SuppressWarnings("unchecked") // reading data stored by writeObject
289 private void readObject(ObjectInputStream stream)
290 throws IOException, ClassNotFoundException {
291 stream.defaultReadObject();
292 factory = (Supplier<? extends Set<V>>) stream.readObject();
293 Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject();
294 setMap(map);
295 }
296
297 @GwtIncompatible("not needed in emulated source")
298 private static final long serialVersionUID = 0;
299 }
300
301 /**
302 * Creates a new {@code SortedSetMultimap} that uses the provided map and
303 * factory. It can generate a multimap based on arbitrary {@link Map} and
304 * {@link SortedSet} classes.
305 *
306 * <p>The {@code factory}-generated and {@code map} classes determine the
307 * multimap iteration order. They also specify the behavior of the
308 * {@code equals}, {@code hashCode}, and {@code toString} methods for the
309 * multimap and its returned views. However, the multimap's {@code get}
310 * method returns instances of a different class than {@code factory.get()}
311 * does.
312 *
313 * <p>The multimap is serializable if {@code map}, {@code factory}, the
314 * sets generated by {@code factory}, and the multimap contents are all
315 * serializable.
316 *
317 * <p>The multimap is not threadsafe when any concurrent operations update the
318 * multimap, even if {@code map} and the instances generated by
319 * {@code factory} are. Concurrent read operations will work correctly. To
320 * allow concurrent update operations, wrap the multimap with a call to
321 * {@link #synchronizedSortedSetMultimap}.
322 *
323 * <p>Call this method only when the simpler methods
324 * {@link TreeMultimap#create()} and
325 * {@link TreeMultimap#create(Comparator, Comparator)} won't suffice.
326 *
327 * <p>Note: the multimap assumes complete ownership over of {@code map} and
328 * the sets returned by {@code factory}. Those objects should not be manually
329 * updated and they should not use soft, weak, or phantom references.
330 *
331 * @param map place to store the mapping from each key to its corresponding
332 * values
333 * @param factory supplier of new, empty sorted sets that will each hold
334 * all values for a given key
335 * @throws IllegalArgumentException if {@code map} is not empty
336 */
337 public static <K, V> SortedSetMultimap<K, V> newSortedSetMultimap(
338 Map<K, Collection<V>> map,
339 final Supplier<? extends SortedSet<V>> factory) {
340 return new CustomSortedSetMultimap<K, V>(map, factory);
341 }
342
343 private static class CustomSortedSetMultimap<K, V>
344 extends AbstractSortedSetMultimap<K, V> {
345 transient Supplier<? extends SortedSet<V>> factory;
346 transient Comparator<? super V> valueComparator;
347
348 CustomSortedSetMultimap(Map<K, Collection<V>> map,
349 Supplier<? extends SortedSet<V>> factory) {
350 super(map);
351 this.factory = checkNotNull(factory);
352 valueComparator = factory.get().comparator();
353 }
354
355 @Override protected SortedSet<V> createCollection() {
356 return factory.get();
357 }
358
359 @Override public Comparator<? super V> valueComparator() {
360 return valueComparator;
361 }
362
363 /** @serialData the factory and the backing map */
364 @GwtIncompatible("java.io.ObjectOutputStream")
365 private void writeObject(ObjectOutputStream stream) throws IOException {
366 stream.defaultWriteObject();
367 stream.writeObject(factory);
368 stream.writeObject(backingMap());
369 }
370
371 @GwtIncompatible("java.io.ObjectInputStream")
372 @SuppressWarnings("unchecked") // reading data stored by writeObject
373 private void readObject(ObjectInputStream stream)
374 throws IOException, ClassNotFoundException {
375 stream.defaultReadObject();
376 factory = (Supplier<? extends SortedSet<V>>) stream.readObject();
377 valueComparator = factory.get().comparator();
378 Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject();
379 setMap(map);
380 }
381
382 @GwtIncompatible("not needed in emulated source")
383 private static final long serialVersionUID = 0;
384 }
385
386 /**
387 * Copies each key-value mapping in {@code source} into {@code dest}, with
388 * its key and value reversed.
389 *
390 * @param source any multimap
391 * @param dest the multimap to copy into; usually empty
392 * @return {@code dest}
393 */
394 public static <K, V, M extends Multimap<K, V>> M invertFrom(
395 Multimap<? extends V, ? extends K> source, M dest) {
396 checkNotNull(dest);
397 for (Map.Entry<? extends V, ? extends K> entry : source.entries()) {
398 dest.put(entry.getValue(), entry.getKey());
399 }
400 return dest;
401 }
402
403 /**
404 * Returns a synchronized (thread-safe) multimap backed by the specified
405 * multimap. In order to guarantee serial access, it is critical that
406 * <b>all</b> access to the backing multimap is accomplished through the
407 * returned multimap.
408 *
409 * <p>It is imperative that the user manually synchronize on the returned
410 * multimap when accessing any of its collection views: <pre> {@code
411 *
412 * Multimap<K, V> m = Multimaps.synchronizedMultimap(
413 * HashMultimap.<K, V>create());
414 * ...
415 * Set<K> s = m.keySet(); // Needn't be in synchronized block
416 * ...
417 * synchronized (m) { // Synchronizing on m, not s!
418 * Iterator<K> i = s.iterator(); // Must be in synchronized block
419 * while (i.hasNext()) {
420 * foo(i.next());
421 * }
422 * }}</pre>
423 *
424 * Failure to follow this advice may result in non-deterministic behavior.
425 *
426 * <p>Note that the generated multimap's {@link Multimap#removeAll} and
427 * {@link Multimap#replaceValues} methods return collections that aren't
428 * synchronized.
429 *
430 * <p>The returned multimap will be serializable if the specified multimap is
431 * serializable.
432 *
433 * @param multimap the multimap to be wrapped in a synchronized view
434 * @return a synchronized view of the specified multimap
435 */
436 public static <K, V> Multimap<K, V> synchronizedMultimap(
437 Multimap<K, V> multimap) {
438 return Synchronized.multimap(multimap, null);
439 }
440
441 /**
442 * Returns an unmodifiable view of the specified multimap. Query operations on
443 * the returned multimap "read through" to the specified multimap, and
444 * attempts to modify the returned multimap, either directly or through the
445 * multimap's views, result in an {@code UnsupportedOperationException}.
446 *
447 * <p>Note that the generated multimap's {@link Multimap#removeAll} and
448 * {@link Multimap#replaceValues} methods return collections that are
449 * modifiable.
450 *
451 * <p>The returned multimap will be serializable if the specified multimap is
452 * serializable.
453 *
454 * @param delegate the multimap for which an unmodifiable view is to be
455 * returned
456 * @return an unmodifiable view of the specified multimap
457 */
458 public static <K, V> Multimap<K, V> unmodifiableMultimap(
459 Multimap<K, V> delegate) {
460 return new UnmodifiableMultimap<K, V>(delegate);
461 }
462
463 private static class UnmodifiableMultimap<K, V>
464 extends ForwardingMultimap<K, V> implements Serializable {
465 final Multimap<K, V> delegate;
466 transient Collection<Entry<K, V>> entries;
467 transient Multiset<K> keys;
468 transient Set<K> keySet;
469 transient Collection<V> values;
470 transient Map<K, Collection<V>> map;
471
472 UnmodifiableMultimap(final Multimap<K, V> delegate) {
473 this.delegate = checkNotNull(delegate);
474 }
475
476 @Override protected Multimap<K, V> delegate() {
477 return delegate;
478 }
479
480 @Override public void clear() {
481 throw new UnsupportedOperationException();
482 }
483
484 @Override public Map<K, Collection<V>> asMap() {
485 Map<K, Collection<V>> result = map;
486 if (result == null) {
487 final Map<K, Collection<V>> unmodifiableMap
488 = Collections.unmodifiableMap(delegate.asMap());
489 map = result = new ForwardingMap<K, Collection<V>>() {
490 @Override protected Map<K, Collection<V>> delegate() {
491 return unmodifiableMap;
492 }
493
494 Set<Entry<K, Collection<V>>> entrySet;
495
496 @Override public Set<Map.Entry<K, Collection<V>>> entrySet() {
497 Set<Entry<K, Collection<V>>> result = entrySet;
498 return (result == null)
499 ? entrySet
500 = unmodifiableAsMapEntries(unmodifiableMap.entrySet())
501 : result;
502 }
503
504 @Override public Collection<V> get(Object key) {
505 Collection<V> collection = unmodifiableMap.get(key);
506 return (collection == null)
507 ? null : unmodifiableValueCollection(collection);
508 }
509
510 Collection<Collection<V>> asMapValues;
511
512 @Override public Collection<Collection<V>> values() {
513 Collection<Collection<V>> result = asMapValues;
514 return (result == null)
515 ? asMapValues
516 = new UnmodifiableAsMapValues<V>(unmodifiableMap.values())
517 : result;
518 }
519
520 @Override public boolean containsValue(Object o) {
521 return values().contains(o);
522 }
523 };
524 }
525 return result;
526 }
527
528 @Override public Collection<Entry<K, V>> entries() {
529 Collection<Entry<K, V>> result = entries;
530 if (result == null) {
531 entries = result = unmodifiableEntries(delegate.entries());
532 }
533 return result;
534 }
535
536 @Override public Collection<V> get(K key) {
537 return unmodifiableValueCollection(delegate.get(key));
538 }
539
540 @Override public Multiset<K> keys() {
541 Multiset<K> result = keys;
542 if (result == null) {
543 keys = result = Multisets.unmodifiableMultiset(delegate.keys());
544 }
545 return result;
546 }
547
548 @Override public Set<K> keySet() {
549 Set<K> result = keySet;
550 if (result == null) {
551 keySet = result = Collections.unmodifiableSet(delegate.keySet());
552 }
553 return result;
554 }
555
556 @Override public boolean put(K key, V value) {
557 throw new UnsupportedOperationException();
558 }
559
560 @Override public boolean putAll(K key,
561 @SuppressWarnings("hiding") Iterable<? extends V> values) {
562 throw new UnsupportedOperationException();
563 }
564
565 @Override
566 public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
567 throw new UnsupportedOperationException();
568 }
569
570 @Override public boolean remove(Object key, Object value) {
571 throw new UnsupportedOperationException();
572 }
573
574 @Override public Collection<V> removeAll(Object key) {
575 throw new UnsupportedOperationException();
576 }
577
578 @Override public Collection<V> replaceValues(K key,
579 @SuppressWarnings("hiding") Iterable<? extends V> values) {
580 throw new UnsupportedOperationException();
581 }
582
583 @Override public Collection<V> values() {
584 Collection<V> result = values;
585 if (result == null) {
586 values = result = Collections.unmodifiableCollection(delegate.values());
587 }
588 return result;
589 }
590
591 private static final long serialVersionUID = 0;
592 }
593
594 private static class UnmodifiableAsMapValues<V>
595 extends ForwardingCollection<Collection<V>> {
596 final Collection<Collection<V>> delegate;
597 UnmodifiableAsMapValues(Collection<Collection<V>> delegate) {
598 this.delegate = Collections.unmodifiableCollection(delegate);
599 }
600 @Override protected Collection<Collection<V>> delegate() {
601 return delegate;
602 }
603 @Override public Iterator<Collection<V>> iterator() {
604 final Iterator<Collection<V>> iterator = delegate.iterator();
605 return new Iterator<Collection<V>>() {
606 public boolean hasNext() {
607 return iterator.hasNext();
608 }
609 public Collection<V> next() {
610 return unmodifiableValueCollection(iterator.next());
611 }
612 public void remove() {
613 throw new UnsupportedOperationException();
614 }
615 };
616 }
617 @Override public Object[] toArray() {
618 return standardToArray();
619 }
620 @Override public <T> T[] toArray(T[] array) {
621 return standardToArray(array);
622 }
623 @Override public boolean contains(Object o) {
624 return standardContains(o);
625 }
626 @Override public boolean containsAll(Collection<?> c) {
627 return standardContainsAll(c);
628 }
629 }
630
631 private static class UnmodifiableListMultimap<K, V>
632 extends UnmodifiableMultimap<K, V> implements ListMultimap<K, V> {
633 UnmodifiableListMultimap(ListMultimap<K, V> delegate) {
634 super(delegate);
635 }
636 @Override public ListMultimap<K, V> delegate() {
637 return (ListMultimap<K, V>) super.delegate();
638 }
639 @Override public List<V> get(K key) {
640 return Collections.unmodifiableList(delegate().get(key));
641 }
642 @Override public List<V> removeAll(Object key) {
643 throw new UnsupportedOperationException();
644 }
645 @Override public List<V> replaceValues(
646 K key, @SuppressWarnings("hiding") Iterable<? extends V> values) {
647 throw new UnsupportedOperationException();
648 }
649 private static final long serialVersionUID = 0;
650 }
651
652 private static class UnmodifiableSetMultimap<K, V>
653 extends UnmodifiableMultimap<K, V> implements SetMultimap<K, V> {
654 UnmodifiableSetMultimap(SetMultimap<K, V> delegate) {
655 super(delegate);
656 }
657 @Override public SetMultimap<K, V> delegate() {
658 return (SetMultimap<K, V>) super.delegate();
659 }
660 @Override public Set<V> get(K key) {
661 /*
662 * Note that this doesn't return a SortedSet when delegate is a
663 * SortedSetMultiset, unlike (SortedSet<V>) super.get().
664 */
665 return Collections.unmodifiableSet(delegate().get(key));
666 }
667 @Override public Set<Map.Entry<K, V>> entries() {
668 return Maps.unmodifiableEntrySet(delegate().entries());
669 }
670 @Override public Set<V> removeAll(Object key) {
671 throw new UnsupportedOperationException();
672 }
673 @Override public Set<V> replaceValues(
674 K key, @SuppressWarnings("hiding") Iterable<? extends V> values) {
675 throw new UnsupportedOperationException();
676 }
677 private static final long serialVersionUID = 0;
678 }
679
680 private static class UnmodifiableSortedSetMultimap<K, V>
681 extends UnmodifiableSetMultimap<K, V> implements SortedSetMultimap<K, V> {
682 UnmodifiableSortedSetMultimap(SortedSetMultimap<K, V> delegate) {
683 super(delegate);
684 }
685 @Override public SortedSetMultimap<K, V> delegate() {
686 return (SortedSetMultimap<K, V>) super.delegate();
687 }
688 @Override public SortedSet<V> get(K key) {
689 return Collections.unmodifiableSortedSet(delegate().get(key));
690 }
691 @Override public SortedSet<V> removeAll(Object key) {
692 throw new UnsupportedOperationException();
693 }
694 @Override public SortedSet<V> replaceValues(
695 K key, @SuppressWarnings("hiding") Iterable<? extends V> values) {
696 throw new UnsupportedOperationException();
697 }
698 public Comparator<? super V> valueComparator() {
699 return delegate().valueComparator();
700 }
701 private static final long serialVersionUID = 0;
702 }
703
704 /**
705 * Returns a synchronized (thread-safe) {@code SetMultimap} backed by the
706 * specified multimap.
707 *
708 * <p>You must follow the warnings described in {@link #synchronizedMultimap}.
709 *
710 * <p>The returned multimap will be serializable if the specified multimap is
711 * serializable.
712 *
713 * @param multimap the multimap to be wrapped
714 * @return a synchronized view of the specified multimap
715 */
716 public static <K, V> SetMultimap<K, V> synchronizedSetMultimap(
717 SetMultimap<K, V> multimap) {
718 return Synchronized.setMultimap(multimap, null);
719 }
720
721 /**
722 * Returns an unmodifiable view of the specified {@code SetMultimap}. Query
723 * operations on the returned multimap "read through" to the specified
724 * multimap, and attempts to modify the returned multimap, either directly or
725 * through the multimap's views, result in an
726 * {@code UnsupportedOperationException}.
727 *
728 * <p>Note that the generated multimap's {@link Multimap#removeAll} and
729 * {@link Multimap#replaceValues} methods return collections that are
730 * modifiable.
731 *
732 * <p>The returned multimap will be serializable if the specified multimap is
733 * serializable.
734 *
735 * @param delegate the multimap for which an unmodifiable view is to be
736 * returned
737 * @return an unmodifiable view of the specified multimap
738 */
739 public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(
740 SetMultimap<K, V> delegate) {
741 return new UnmodifiableSetMultimap<K, V>(delegate);
742 }
743
744 /**
745 * Returns a synchronized (thread-safe) {@code SortedSetMultimap} backed by
746 * the specified multimap.
747 *
748 * <p>You must follow the warnings described in {@link #synchronizedMultimap}.
749 *
750 * <p>The returned multimap will be serializable if the specified multimap is
751 * serializable.
752 *
753 * @param multimap the multimap to be wrapped
754 * @return a synchronized view of the specified multimap
755 */
756 public static <K, V> SortedSetMultimap<K, V>
757 synchronizedSortedSetMultimap(SortedSetMultimap<K, V> multimap) {
758 return Synchronized.sortedSetMultimap(multimap, null);
759 }
760
761 /**
762 * Returns an unmodifiable view of the specified {@code SortedSetMultimap}.
763 * Query operations on the returned multimap "read through" to the specified
764 * multimap, and attempts to modify the returned multimap, either directly or
765 * through the multimap's views, result in an
766 * {@code UnsupportedOperationException}.
767 *
768 * <p>Note that the generated multimap's {@link Multimap#removeAll} and
769 * {@link Multimap#replaceValues} methods return collections that are
770 * modifiable.
771 *
772 * <p>The returned multimap will be serializable if the specified multimap is
773 * serializable.
774 *
775 * @param delegate the multimap for which an unmodifiable view is to be
776 * returned
777 * @return an unmodifiable view of the specified multimap
778 */
779 public static <K, V> SortedSetMultimap<K, V> unmodifiableSortedSetMultimap(
780 SortedSetMultimap<K, V> delegate) {
781 return new UnmodifiableSortedSetMultimap<K, V>(delegate);
782 }
783
784 /**
785 * Returns a synchronized (thread-safe) {@code ListMultimap} backed by the
786 * specified multimap.
787 *
788 * <p>You must follow the warnings described in {@link #synchronizedMultimap}.
789 *
790 * @param multimap the multimap to be wrapped
791 * @return a synchronized view of the specified multimap
792 */
793 public static <K, V> ListMultimap<K, V> synchronizedListMultimap(
794 ListMultimap<K, V> multimap) {
795 return Synchronized.listMultimap(multimap, null);
796 }
797
798 /**
799 * Returns an unmodifiable view of the specified {@code ListMultimap}. Query
800 * operations on the returned multimap "read through" to the specified
801 * multimap, and attempts to modify the returned multimap, either directly or
802 * through the multimap's views, result in an
803 * {@code UnsupportedOperationException}.
804 *
805 * <p>Note that the generated multimap's {@link Multimap#removeAll} and
806 * {@link Multimap#replaceValues} methods return collections that are
807 * modifiable.
808 *
809 * <p>The returned multimap will be serializable if the specified multimap is
810 * serializable.
811 *
812 * @param delegate the multimap for which an unmodifiable view is to be
813 * returned
814 * @return an unmodifiable view of the specified multimap
815 */
816 public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(
817 ListMultimap<K, V> delegate) {
818 return new UnmodifiableListMultimap<K, V>(delegate);
819 }
820
821 /**
822 * Returns an unmodifiable view of the specified collection, preserving the
823 * interface for instances of {@code SortedSet}, {@code Set}, {@code List} and
824 * {@code Collection}, in that order of preference.
825 *
826 * @param collection the collection for which to return an unmodifiable view
827 * @return an unmodifiable view of the collection
828 */
829 private static <V> Collection<V> unmodifiableValueCollection(
830 Collection<V> collection) {
831 if (collection instanceof SortedSet) {
832 return Collections.unmodifiableSortedSet((SortedSet<V>) collection);
833 } else if (collection instanceof Set) {
834 return Collections.unmodifiableSet((Set<V>) collection);
835 } else if (collection instanceof List) {
836 return Collections.unmodifiableList((List<V>) collection);
837 }
838 return Collections.unmodifiableCollection(collection);
839 }
840
841 /**
842 * Returns an unmodifiable view of the specified multimap {@code asMap} entry.
843 * The {@link Entry#setValue} operation throws an {@link
844 * UnsupportedOperationException}, and the collection returned by {@code
845 * getValue} is also an unmodifiable (type-preserving) view. This also has the
846 * side-effect of redefining equals to comply with the Map.Entry contract, and
847 * to avoid a possible nefarious implementation of equals.
848 *
849 * @param entry the entry for which to return an unmodifiable view
850 * @return an unmodifiable view of the entry
851 */
852 private static <K, V> Map.Entry<K, Collection<V>> unmodifiableAsMapEntry(
853 final Map.Entry<K, Collection<V>> entry) {
854 checkNotNull(entry);
855 return new AbstractMapEntry<K, Collection<V>>() {
856 @Override public K getKey() {
857 return entry.getKey();
858 }
859
860 @Override public Collection<V> getValue() {
861 return unmodifiableValueCollection(entry.getValue());
862 }
863 };
864 }
865
866 /**
867 * Returns an unmodifiable view of the specified collection of entries. The
868 * {@link Entry#setValue} operation throws an {@link
869 * UnsupportedOperationException}. If the specified collection is a {@code
870 * Set}, the returned collection is also a {@code Set}.
871 *
872 * @param entries the entries for which to return an unmodifiable view
873 * @return an unmodifiable view of the entries
874 */
875 private static <K, V> Collection<Entry<K, V>> unmodifiableEntries(
876 Collection<Entry<K, V>> entries) {
877 if (entries instanceof Set) {
878 return Maps.unmodifiableEntrySet((Set<Entry<K, V>>) entries);
879 }
880 return new Maps.UnmodifiableEntries<K, V>(
881 Collections.unmodifiableCollection(entries));
882 }
883
884 /**
885 * Returns an unmodifiable view of the specified set of {@code asMap} entries.
886 * The {@link Entry#setValue} operation throws an {@link
887 * UnsupportedOperationException}, as do any operations that attempt to modify
888 * the returned collection.
889 *
890 * @param asMapEntries the {@code asMap} entries for which to return an
891 * unmodifiable view
892 * @return an unmodifiable view of the collection entries
893 */
894 private static <K, V> Set<Entry<K, Collection<V>>> unmodifiableAsMapEntries(
895 Set<Entry<K, Collection<V>>> asMapEntries) {
896 return new UnmodifiableAsMapEntries<K, V>(
897 Collections.unmodifiableSet(asMapEntries));
898 }
899
900 /** @see Multimaps#unmodifiableAsMapEntries */
901 static class UnmodifiableAsMapEntries<K, V>
902 extends ForwardingSet<Entry<K, Collection<V>>> {
903 private final Set<Entry<K, Collection<V>>> delegate;
904 UnmodifiableAsMapEntries(Set<Entry<K, Collection<V>>> delegate) {
905 this.delegate = delegate;
906 }
907
908 @Override protected Set<Entry<K, Collection<V>>> delegate() {
909 return delegate;
910 }
911
912 @Override public Iterator<Entry<K, Collection<V>>> iterator() {
913 final Iterator<Entry<K, Collection<V>>> iterator = delegate.iterator();
914 return new ForwardingIterator<Entry<K, Collection<V>>>() {
915 @Override protected Iterator<Entry<K, Collection<V>>> delegate() {
916 return iterator;
917 }
918 @Override public Entry<K, Collection<V>> next() {
919 return unmodifiableAsMapEntry(iterator.next());
920 }
921 };
922 }
923
924 @Override public Object[] toArray() {
925 return standardToArray();
926 }
927
928 @Override public <T> T[] toArray(T[] array) {
929 return standardToArray(array);
930 }
931
932 @Override public boolean contains(Object o) {
933 return Maps.containsEntryImpl(delegate(), o);
934 }
935
936 @Override public boolean containsAll(Collection<?> c) {
937 return standardContainsAll(c);
938 }
939
940 @Override public boolean equals(@Nullable Object object) {
941 return standardEquals(object);
942 }
943 }
944
945 /**
946 * Returns a multimap view of the specified map. The multimap is backed by the
947 * map, so changes to the map are reflected in the multimap, and vice versa.
948 * If the map is modified while an iteration over one of the multimap's
949 * collection views is in progress (except through the iterator's own {@code
950 * remove} operation, or through the {@code setValue} operation on a map entry
951 * returned by the iterator), the results of the iteration are undefined.
952 *
953 * <p>The multimap supports mapping removal, which removes the corresponding
954 * mapping from the map. It does not support any operations which might add
955 * mappings, such as {@code put}, {@code putAll} or {@code replaceValues}.
956 *
957 * <p>The returned multimap will be serializable if the specified map is
958 * serializable.
959 *
960 * @param map the backing map for the returned multimap view
961 */
962 public static <K, V> SetMultimap<K, V> forMap(Map<K, V> map) {
963 return new MapMultimap<K, V>(map);
964 }
965
966 /** @see Multimaps#forMap */
967 private static class MapMultimap<K, V>
968 implements SetMultimap<K, V>, Serializable {
969 final Map<K, V> map;
970 transient Map<K, Collection<V>> asMap;
971
972 MapMultimap(Map<K, V> map) {
973 this.map = checkNotNull(map);
974 }
975
976 public int size() {
977 return map.size();
978 }
979
980 public boolean isEmpty() {
981 return map.isEmpty();
982 }
983
984 public boolean containsKey(Object key) {
985 return map.containsKey(key);
986 }
987
988 public boolean containsValue(Object value) {
989 return map.containsValue(value);
990 }
991
992 public boolean containsEntry(Object key, Object value) {
993 return map.entrySet().contains(Maps.immutableEntry(key, value));
994 }
995
996 public Set<V> get(final K key) {
997 return new AbstractSet<V>() {
998 @Override public Iterator<V> iterator() {
999 return new Iterator<V>() {
1000 int i;
1001
1002 public boolean hasNext() {
1003 return (i == 0) && map.containsKey(key);
1004 }
1005
1006 public V next() {
1007 if (!hasNext()) {
1008 throw new NoSuchElementException();
1009 }
1010 i++;
1011 return map.get(key);
1012 }
1013
1014 public void remove() {
1015 checkState(i == 1);
1016 i = -1;
1017 map.remove(key);
1018 }
1019 };
1020 }
1021
1022 @Override public int size() {
1023 return map.containsKey(key) ? 1 : 0;
1024 }
1025 };
1026 }
1027
1028 public boolean put(K key, V value) {
1029 throw new UnsupportedOperationException();
1030 }
1031
1032 public boolean putAll(K key, Iterable<? extends V> values) {
1033 throw new UnsupportedOperationException();
1034 }
1035
1036 public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
1037 throw new UnsupportedOperationException();
1038 }
1039
1040 public Set<V> replaceValues(K key, Iterable<? extends V> values) {
1041 throw new UnsupportedOperationException();
1042 }
1043
1044 public boolean remove(Object key, Object value) {
1045 return map.entrySet().remove(Maps.immutableEntry(key, value));
1046 }
1047
1048 public Set<V> removeAll(Object key) {
1049 Set<V> values = new HashSet<V>(2);
1050 if (!map.containsKey(key)) {
1051 return values;
1052 }
1053 values.add(map.remove(key));
1054 return values;
1055 }
1056
1057 public void clear() {
1058 map.clear();
1059 }
1060
1061 public Set<K> keySet() {
1062 return map.keySet();
1063 }
1064
1065 public Multiset<K> keys() {
1066 return Multisets.forSet(map.keySet());
1067 }
1068
1069 public Collection<V> values() {
1070 return map.values();
1071 }
1072
1073 public Set<Entry<K, V>> entries() {
1074 return map.entrySet();
1075 }
1076
1077 public Map<K, Collection<V>> asMap() {
1078 Map<K, Collection<V>> result = asMap;
1079 if (result == null) {
1080 asMap = result = new AsMap();
1081 }
1082 return result;
1083 }
1084
1085 @Override public boolean equals(@Nullable Object object) {
1086 if (object == this) {
1087 return true;
1088 }
1089 if (object instanceof Multimap) {
1090 Multimap<?, ?> that = (Multimap<?, ?>) object;
1091 return this.size() == that.size() && asMap().equals(that.asMap());
1092 }
1093 return false;
1094 }
1095
1096 @Override public int hashCode() {
1097 return map.hashCode();
1098 }
1099
1100 private static final MapJoiner JOINER
1101 = Joiner.on("], ").withKeyValueSeparator("=[").useForNull("null");
1102
1103 @Override public String toString() {
1104 if (map.isEmpty()) {
1105 return "{}";
1106 }
1107 StringBuilder builder
1108 = Collections2.newStringBuilderForCollection(map.size()).append('{');
1109 JOINER.appendTo(builder, map);
1110 return builder.append("]}").toString();
1111 }
1112
1113 /** @see MapMultimap#asMap */
1114 class AsMapEntries extends AbstractSet<Entry<K, Collection<V>>> {
1115 @Override public int size() {
1116 return map.size();
1117 }
1118
1119 @Override public Iterator<Entry<K, Collection<V>>> iterator() {
1120 return new Iterator<Entry<K, Collection<V>>>() {
1121 final Iterator<K> keys = map.keySet().iterator();
1122
1123 public boolean hasNext() {
1124 return keys.hasNext();
1125 }
1126 public Entry<K, Collection<V>> next() {
1127 final K key = keys.next();
1128 return new AbstractMapEntry<K, Collection<V>>() {
1129 @Override public K getKey() {
1130 return key;
1131 }
1132 @Override public Collection<V> getValue() {
1133 return get(key);
1134 }
1135 };
1136 }
1137 public void remove() {
1138 keys.remove();
1139 }
1140 };
1141 }
1142
1143 @Override public boolean contains(Object o) {
1144 if (!(o instanceof Entry)) {
1145 return false;
1146 }
1147 Entry<?, ?> entry = (Entry<?, ?>) o;
1148 if (!(entry.getValue() instanceof Set)) {
1149 return false;
1150 }
1151 Set<?> set = (Set<?>) entry.getValue();
1152 return (set.size() == 1)
1153 && containsEntry(entry.getKey(), set.iterator().next());
1154 }
1155
1156 @Override public boolean remove(Object o) {
1157 if (!(o instanceof Entry)) {
1158 return false;
1159 }
1160 Entry<?, ?> entry = (Entry<?, ?>) o;
1161 if (!(entry.getValue() instanceof Set)) {
1162 return false;
1163 }
1164 Set<?> set = (Set<?>) entry.getValue();
1165 return (set.size() == 1)
1166 && map.entrySet().remove(
1167 Maps.immutableEntry(entry.getKey(), set.iterator().next()));
1168 }
1169 }
1170
1171 /** @see MapMultimap#asMap */
1172 class AsMap extends Maps.ImprovedAbstractMap<K, Collection<V>> {
1173 @Override protected Set<Entry<K, Collection<V>>> createEntrySet() {
1174 return new AsMapEntries();
1175 }
1176
1177 // The following methods are included for performance.
1178
1179 @Override public boolean containsKey(Object key) {
1180 return map.containsKey(key);
1181 }
1182
1183 @SuppressWarnings("unchecked")
1184 @Override public Collection<V> get(Object key) {
1185 Collection<V> collection = MapMultimap.this.get((K) key);
1186 return collection.isEmpty() ? null : collection;
1187 }
1188
1189 @Override public Collection<V> remove(Object key) {
1190 Collection<V> collection = removeAll(key);
1191 return collection.isEmpty() ? null : collection;
1192 }
1193 }
1194 private static final long serialVersionUID = 7845222491160860175L;
1195 }
1196
1197 /**
1198 * Returns a view of a multimap where each value is transformed by a function.
1199 * All other properties of the multimap, such as iteration order, are left
1200 * intact. For example, the code: <pre> {@code
1201 *
1202 * Multimap<String, Integer> multimap =
1203 * ImmutableSetMultimap.of("a", 2, "b", -3, "b", -3, "a", 4, "c", 6);
1204 * Function<Integer, String> square = new Function<Integer, String>() {
1205 * public String apply(Integer in) {
1206 * return Integer.toString(in * in);
1207 * }
1208 * };
1209 * Multimap<String, String> transformed =
1210 * Multimaps.transformValues(multimap, square);
1211 * System.out.println(transformed);}</pre>
1212 *
1213 * ... prints {@code {a=[4, 16], b=[9, 9], c=[6]}}.
1214 *
1215 * <p>Changes in the underlying multimap are reflected in this view.
1216 * Conversely, this view supports removal operations, and these are reflected
1217 * in the underlying multimap.
1218 *
1219 * <p>It's acceptable for the underlying multimap to contain null keys, and
1220 * even null values provided that the function is capable of accepting null
1221 * input. The transformed multimap might contain null values, if the function
1222 * sometimes gives a null result.
1223 *
1224 * <p>The returned multimap is not thread-safe or serializable, even if the
1225 * underlying multimap is. The {@code equals} and {@code hashCode} methods
1226 * of the returned multimap are meaningless, since there is not a definition
1227 * of {@code equals} or {@code hashCode} for general collections, and
1228 * {@code get()} will return a general {@code Collection} as opposed to a
1229 * {@code List} or a {@code Set}.
1230 *
1231 * <p>The function is applied lazily, invoked when needed. This is necessary
1232 * for the returned multimap to be a view, but it means that the function will
1233 * be applied many times for bulk operations like
1234 * {@link Multimap#containsValue} and {@code Multimap.toString()}. For this to
1235 * perform well, {@code function} should be fast. To avoid lazy evaluation
1236 * when the returned multimap doesn't need to be a view, copy the returned
1237 * multimap into a new multimap of your choosing.
1238 *
1239 * @since 7
1240 */
1241 @Beta
1242 @GwtIncompatible(value = "untested")
1243 public static <K, V1, V2> Multimap<K, V2> transformValues(
1244 Multimap<K, V1> fromMultimap, final Function<? super V1, V2> function) {
1245 checkNotNull(function);
1246 EntryTransformer<K, V1, V2> transformer =
1247 new EntryTransformer<K, V1, V2>() {
1248 public V2 transformEntry(K key, V1 value) {
1249 return function.apply(value);
1250 }
1251 };
1252 return transformEntries(fromMultimap, transformer);
1253 }
1254
1255 /**
1256 * Returns a view of a multimap whose values are derived from the original
1257 * multimap's entries. In contrast to {@link #transformValues}, this method's
1258 * entry-transformation logic may depend on the key as well as the value.
1259 *
1260 * <p>All other properties of the transformed multimap, such as iteration
1261 * order, are left intact. For example, the code: <pre> {@code
1262 *
1263 * SetMultimap<String, Integer> multimap =
1264 * ImmutableSetMultimap.of("a", 1, "a", 4, "b", -6);
1265 * EntryTransformer<String, Integer, String> transformer =
1266 * new EntryTransformer<String, Integer, String>() {
1267 * public String transformEntry(String key, Integer value) {
1268 * return (value >= 0) ? key : "no" + key;
1269 * }
1270 * };
1271 * Multimap<String, String> transformed =
1272 * Multimaps.transformEntries(multimap, transformer);
1273 * System.out.println(transformed);}</pre>
1274 *
1275 * ... prints {@code {a=[a, a], b=[nob]}}.
1276 *
1277 * <p>Changes in the underlying multimap are reflected in this view.
1278 * Conversely, this view supports removal operations, and these are reflected
1279 * in the underlying multimap.
1280 *
1281 * <p>It's acceptable for the underlying multimap to contain null keys and
1282 * null values provided that the transformer is capable of accepting null
1283 * inputs. The transformed multimap might contain null values if the
1284 * transformer sometimes gives a null result.
1285 *
1286 * <p>The returned multimap is not thread-safe or serializable, even if the
1287 * underlying multimap is. The {@code equals} and {@code hashCode} methods
1288 * of the returned multimap are meaningless, since there is not a definition
1289 * of {@code equals} or {@code hashCode} for general collections, and
1290 * {@code get()} will return a general {@code Collection} as opposed to a
1291 * {@code List} or a {@code Set}.
1292 *
1293 * <p>The transformer is applied lazily, invoked when needed. This is
1294 * necessary for the returned multimap to be a view, but it means that the
1295 * transformer will be applied many times for bulk operations like {@link
1296 * Multimap#containsValue} and {@link Object#toString}. For this to perform
1297 * well, {@code transformer} should be fast. To avoid lazy evaluation when the
1298 * returned multimap doesn't need to be a view, copy the returned multimap
1299 * into a new multimap of your choosing.
1300 *
1301 * <p><b>Warning:</b> This method assumes that for any instance {@code k} of
1302 * {@code EntryTransformer} key type {@code K}, {@code k.equals(k2)} implies
1303 * that {@code k2} is also of type {@code K}. Using an {@code
1304 * EntryTransformer} key type for which this may not hold, such as {@code
1305 * ArrayList}, may risk a {@code ClassCastException} when calling methods on
1306 * the transformed multimap.
1307 *
1308 * @since 7
1309 */
1310 @Beta
1311 @GwtIncompatible(value = "untested")
1312 public static <K, V1, V2> Multimap<K, V2> transformEntries(
1313 Multimap<K, V1> fromMap,
1314 EntryTransformer<? super K, ? super V1, V2> transformer) {
1315 return new TransformedEntriesMultimap<K, V1, V2>(fromMap, transformer);
1316 }
1317
1318 @GwtIncompatible(value = "untested")
1319 private static class TransformedEntriesMultimap<K, V1, V2>
1320 implements Multimap<K, V2> {
1321 final Multimap<K, V1> fromMultimap;
1322 final EntryTransformer<? super K, ? super V1, V2> transformer;
1323
1324 TransformedEntriesMultimap(Multimap<K, V1> fromMultimap,
1325 final EntryTransformer<? super K, ? super V1, V2> transformer) {
1326 this.fromMultimap = checkNotNull(fromMultimap);
1327 this.transformer = checkNotNull(transformer);
1328 }
1329
1330 Collection<V2> transform(final K key, Collection<V1> values) {
1331 return Collections2.transform(values, new Function<V1, V2>() {
1332 @Override public V2 apply(V1 value) {
1333 return transformer.transformEntry(key, value);
1334 }
1335 });
1336 }
1337
1338 private transient Map<K, Collection<V2>> asMap;
1339
1340 @Override public Map<K, Collection<V2>> asMap() {
1341 if (asMap == null) {
1342 Map<K, Collection<V2>> aM = Maps.transformEntries(fromMultimap.asMap(),
1343 new EntryTransformer<K, Collection<V1>, Collection<V2>>() {
1344
1345 @Override public Collection<V2> transformEntry(
1346 K key, Collection<V1> value) {
1347 return transform(key, value);
1348 }
1349 });
1350 asMap = aM;
1351 return aM;
1352 }
1353 return asMap;
1354 }
1355
1356 @Override public void clear() {
1357 fromMultimap.clear();
1358 }
1359
1360 @SuppressWarnings("unchecked")
1361 @Override public boolean containsEntry(Object key, Object value) {
1362 Collection<V2> values = get((K) key);
1363 return values.contains(value);
1364 }
1365
1366 @Override public boolean containsKey(Object key) {
1367 return fromMultimap.containsKey(key);
1368 }
1369
1370 @Override public boolean containsValue(Object value) {
1371 return values().contains(value);
1372 }
1373
1374 private transient Collection<Entry<K, V2>> entries;
1375
1376 @Override public Collection<Entry<K, V2>> entries() {
1377 if (entries == null) {
1378 Collection<Entry<K, V2>> es = new TransformedEntries(transformer);
1379 entries = es;
1380 return es;
1381 }
1382 return entries;
1383 }
1384
1385 private class TransformedEntries
1386 extends TransformedCollection<Entry<K, V1>, Entry<K, V2>> {
1387
1388 TransformedEntries(
1389 final EntryTransformer<? super K, ? super V1, V2> transformer) {
1390 super(fromMultimap.entries(),
1391 new Function<Entry<K, V1>, Entry<K, V2>>() {
1392 @Override public Entry<K, V2> apply(final Entry<K, V1> entry) {
1393 return new AbstractMapEntry<K, V2>() {
1394
1395 @Override public K getKey() {
1396 return entry.getKey();
1397 }
1398
1399 @Override public V2 getValue() {
1400 return transformer.transformEntry(
1401 entry.getKey(), entry.getValue());
1402 }
1403 };
1404 }
1405 });
1406 }
1407
1408 @SuppressWarnings("unchecked")
1409 @Override public boolean contains(Object o) {
1410 if (o instanceof Entry) {
1411 Entry<?, ?> entry = (Entry<?, ?>) o;
1412 return containsEntry(entry.getKey(), entry.getValue());
1413 }
1414 return false;
1415 }
1416
1417 @SuppressWarnings("unchecked")
1418 @Override public boolean remove(Object o) {
1419 if (o instanceof Entry) {
1420 Entry<?, ?> entry = (Entry<?, ?>) o;
1421 Collection<V2> values = get((K) entry.getKey());
1422 return values.remove(entry.getValue());
1423 }
1424 return false;
1425 }
1426
1427 }
1428
1429 @Override public Collection<V2> get(final K key) {
1430 return transform(key, fromMultimap.get(key));
1431 }
1432
1433 @Override public boolean isEmpty() {
1434 return fromMultimap.isEmpty();
1435 }
1436
1437 @Override public Set<K> keySet() {
1438 return fromMultimap.keySet();
1439 }
1440
1441 @Override public Multiset<K> keys() {
1442 return fromMultimap.keys();
1443 }
1444
1445 @Override public boolean put(K key, V2 value) {
1446 throw new UnsupportedOperationException();
1447 }
1448
1449 @Override public boolean putAll(K key, Iterable<? extends V2> values) {
1450 throw new UnsupportedOperationException();
1451 }
1452
1453 @Override public boolean putAll(
1454 Multimap<? extends K, ? extends V2> multimap) {
1455 throw new UnsupportedOperationException();
1456 }
1457
1458 @SuppressWarnings("unchecked")
1459 @Override public boolean remove(Object key, Object value) {
1460 return get((K) key).remove(value);
1461 }
1462
1463 @SuppressWarnings("unchecked")
1464 @Override public Collection<V2> removeAll(Object key) {
1465 return transform((K) key, fromMultimap.removeAll(key));
1466 }
1467
1468 @Override public Collection<V2> replaceValues(
1469 K key, Iterable<? extends V2> values) {
1470 throw new UnsupportedOperationException();
1471 }
1472
1473 @Override public int size() {
1474 return fromMultimap.size();
1475 }
1476
1477 private transient Collection<V2> values;
1478
1479 @Override public Collection<V2> values() {
1480 if (values == null) {
1481 Collection<V2> vs = Collections2.transform(
1482 fromMultimap.entries(), new Function<Entry<K, V1>, V2>() {
1483
1484 @Override public V2 apply(Entry<K, V1> entry) {
1485 return transformer.transformEntry(
1486 entry.getKey(), entry.getValue());
1487 }
1488 });
1489 values = vs;
1490 return vs;
1491 }
1492 return values;
1493 }
1494
1495 @Override public boolean equals(Object obj) {
1496 if (obj instanceof Multimap) {
1497 Multimap<?, ?> other = (Multimap<?, ?>) obj;
1498 return asMap().equals(other.asMap());
1499 }
1500 return false;
1501 }
1502
1503 @Override public int hashCode() {
1504 return asMap().hashCode();
1505 }
1506
1507 @Override public String toString() {
1508 return asMap().toString();
1509 }
1510 }
1511
1512 /**
1513 * Returns a view of a {@code ListMultimap} where each value is transformed by
1514 * a function. All other properties of the multimap, such as iteration order,
1515 * are left intact. For example, the code: <pre> {@code
1516 *
1517 * ListMultimap<String, Integer> multimap
1518 * = ImmutableListMultimap.of("a", 4, "a", 16, "b", 9);
1519 * Function<Integer, Double> sqrt =
1520 * new Function<Integer, Double>() {
1521 * public Double apply(Integer in) {
1522 * return Math.sqrt((int) in);
1523 * }
1524 * };
1525 * ListMultimap<String, Double> transformed = Multimaps.transformValues(map,
1526 * sqrt);
1527 * System.out.println(transformed);}</pre>
1528 *
1529 * ... prints {@code {a=[2.0, 4.0], b=[3.0]}}.
1530 *
1531 * <p>Changes in the underlying multimap are reflected in this view.
1532 * Conversely, this view supports removal operations, and these are reflected
1533 * in the underlying multimap.
1534 *
1535 * <p>It's acceptable for the underlying multimap to contain null keys, and
1536 * even null values provided that the function is capable of accepting null
1537 * input. The transformed multimap might contain null values, if the function
1538 * sometimes gives a null result.
1539 *
1540 * <p>The returned multimap is not thread-safe or serializable, even if the
1541 * underlying multimap is.
1542 *
1543 * <p>The function is applied lazily, invoked when needed. This is necessary
1544 * for the returned multimap to be a view, but it means that the function will
1545 * be applied many times for bulk operations like
1546 * {@link Multimap#containsValue} and {@code Multimap.toString()}. For this to
1547 * perform well, {@code function} should be fast. To avoid lazy evaluation
1548 * when the returned multimap doesn't need to be a view, copy the returned
1549 * multimap into a new multimap of your choosing.
1550 *
1551 * @since 7
1552 */
1553 @Beta
1554 @GwtIncompatible(value = "untested")
1555 public static <K, V1, V2> ListMultimap<K, V2> transformValues(
1556 ListMultimap<K, V1> fromMultimap,
1557 final Function<? super V1, V2> function) {
1558 checkNotNull(function);
1559 EntryTransformer<K, V1, V2> transformer =
1560 new EntryTransformer<K, V1, V2>() {
1561 public V2 transformEntry(K key, V1 value) {
1562 return function.apply(value);
1563 }
1564 };
1565 return transformEntries(fromMultimap, transformer);
1566 }
1567
1568 /**
1569 * Returns a view of a {@code ListMultimap} whose values are derived from the
1570 * original multimap's entries. In contrast to
1571 * {@link #transformValues(ListMultimap, Function)}, this method's
1572 * entry-transformation logic may depend on the key as well as the value.
1573 *
1574 * <p>All other properties of the transformed multimap, such as iteration
1575 * order, are left intact. For example, the code: <pre> {@code
1576 *
1577 * Multimap<String, Integer> multimap =
1578 * ImmutableMultimap.of("a", 1, "a", 4, "b", 6);
1579 * EntryTransformer<String, Integer, String> transformer =
1580 * new EntryTransformer<String, Integer, String>() {
1581 * public String transformEntry(String key, Integer value) {
1582 * return key + value;
1583 * }
1584 * };
1585 * Multimap<String, String> transformed =
1586 * Multimaps.transformEntries(multimap, transformer);
1587 * System.out.println(transformed);}</pre>
1588 *
1589 * ... prints {@code {"a"=["a1", "a4"], "b"=["b6"]}}.
1590 *
1591 * <p>Changes in the underlying multimap are reflected in this view.
1592 * Conversely, this view supports removal operations, and these are reflected
1593 * in the underlying multimap.
1594 *
1595 * <p>It's acceptable for the underlying multimap to contain null keys and
1596 * null values provided that the transformer is capable of accepting null
1597 * inputs. The transformed multimap might contain null values if the
1598 * transformer sometimes gives a null result.
1599 *
1600 * <p>The returned multimap is not thread-safe or serializable, even if the
1601 * underlying multimap is.
1602 *
1603 * <p>The transformer is applied lazily, invoked when needed. This is
1604 * necessary for the returned multimap to be a view, but it means that the
1605 * transformer will be applied many times for bulk operations like {@link
1606 * Multimap#containsValue} and {@link Object#toString}. For this to perform
1607 * well, {@code transformer} should be fast. To avoid lazy evaluation when the
1608 * returned multimap doesn't need to be a view, copy the returned multimap
1609 * into a new multimap of your choosing.
1610 *
1611 * <p><b>Warning:</b> This method assumes that for any instance {@code k} of
1612 * {@code EntryTransformer} key type {@code K}, {@code k.equals(k2)} implies
1613 * that {@code k2} is also of type {@code K}. Using an {@code
1614 * EntryTransformer} key type for which this may not hold, such as {@code
1615 * ArrayList}, may risk a {@code ClassCastException} when calling methods on
1616 * the transformed multimap.
1617 *
1618 * @since 7
1619 */
1620 @Beta
1621 @GwtIncompatible(value = "untested")
1622 public static <K, V1, V2> ListMultimap<K, V2> transformEntries(
1623 ListMultimap<K, V1> fromMap,
1624 EntryTransformer<? super K, ? super V1, V2> transformer) {
1625 return new TransformedEntriesListMultimap<K, V1, V2>(fromMap, transformer);
1626 }
1627
1628 @GwtIncompatible(value = "untested")
1629 private static final class TransformedEntriesListMultimap<K, V1, V2>
1630 extends TransformedEntriesMultimap<K, V1, V2>
1631 implements ListMultimap<K, V2> {
1632
1633 TransformedEntriesListMultimap(ListMultimap<K, V1> fromMultimap,
1634 EntryTransformer<? super K, ? super V1, V2> transformer) {
1635 super(fromMultimap, transformer);
1636 }
1637
1638 @Override List<V2> transform(final K key, Collection<V1> values) {
1639 return Lists.transform((List<V1>) values, new Function<V1, V2>() {
1640 @Override public V2 apply(V1 value) {
1641 return transformer.transformEntry(key, value);
1642 }
1643 });
1644 }
1645
1646 @Override public List<V2> get(K key) {
1647 return transform(key, fromMultimap.get(key));
1648 }
1649
1650 @SuppressWarnings("unchecked")
1651 @Override public List<V2> removeAll(Object key) {
1652 return transform((K) key, fromMultimap.removeAll(key));
1653 }
1654
1655 @Override public List<V2> replaceValues(
1656 K key, Iterable<? extends V2> values) {
1657 throw new UnsupportedOperationException();
1658 }
1659 }
1660
1661 /**
1662 * Creates an index {@code ImmutableMultimap} that contains the results of
1663 * applying a specified function to each item in an {@code Iterable} of
1664 * values. Each value will be stored as a value in the resulting multimap,
1665 * yielding a multimap with the same size as the input iterable. The key used
1666 * to store that value in the multimap will be the result of calling the
1667 * function on that value. The resulting multimap is created as an immutable
1668 * snapshot, it does <em>not</em> reflect subsequent changes on the input
1669 * iterable.
1670 *
1671 * <p>For example, <pre> {@code
1672 *
1673 * List<String> badGuys =
1674 * Arrays.asList("Inky", "Blinky", "Pinky", "Pinky", "Clyde");
1675 * Function<String, Integer> stringLengthFunction = ...;
1676 * Multimap<Integer, String> index =
1677 * Multimaps.index(badGuys, stringLengthFunction);
1678 * System.out.println(index);}</pre>
1679 *
1680 * prints <pre> {@code
1681 *
1682 * {4=[Inky], 5=[Pinky, Pinky, Clyde], 6=[Blinky]}}</pre>
1683 *
1684 * The returned multimap is serializable if its keys and values are all
1685 * serializable.
1686 *
1687 * @param values the values to use when constructing the {@code
1688 * ImmutableMultimap}
1689 * @param keyFunction the function used to produce the key for each value
1690 * @return {@code ImmutableMultimap} mapping the result of evaluating the
1691 * function {@code keyFunction} on each value in the input collection to
1692 * that value
1693 * @throws NullPointerException if any of the following cases is true:
1694 * <ul>
1695 * <li>{@code values} is null
1696 * <li>{@code keyFunction} is null
1697 * <li>An element in {@code values} is null
1698 * <li>{@code keyFunction} returns {@code null} for any element of {@code
1699 * values}
1700 * </ul>
1701 */
1702 public static <K, V> ImmutableListMultimap<K, V> index(
1703 Iterable<V> values, Function<? super V, K> keyFunction) {
1704 checkNotNull(keyFunction);
1705 ImmutableListMultimap.Builder<K, V> builder
1706 = ImmutableListMultimap.builder();
1707 for (V value : values) {
1708 checkNotNull(value, values);
1709 builder.put(keyFunction.apply(value), value);
1710 }
1711 return builder.build();
1712 }
1713 }