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 }