Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * Copyright (C) 2007 The Guava Authors
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
    * http://www.apache.org/licenses/LICENSE-2.0
    *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.google.common.collect;
  
  import static com.google.common.base.Preconditions.checkArgument;
  import static com.google.common.base.Preconditions.checkNotNull;
  import static com.google.common.base.Preconditions.checkState;
  
  
  import java.util.HashSet;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  
  import  javax.annotation.Nullable;

Provides static methods acting on or generating a Multimap.

See the Guava User Guide article on Multimaps.

Author(s):
Jared Levy
Robert Konigsberg
Mike Bostock
Louis Wasserman
Since:
2.0 (imported from Google Collections Library)
  
  @GwtCompatible(emulated = true)
  public final class Multimaps {
    private Multimaps() {}

  
Creates a new Multimap that uses the provided map and factory. It can generate a multimap based on arbitrary Map and Collection classes.

The factory-generated and map classes determine the multimap iteration order. They also specify the behavior of the equals, hashCode, and toString methods for the multimap and its returned views. However, the multimap's get method returns instances of a different class than factory.get() does.

The multimap is serializable if map, factory, the collections generated by factory, and the multimap contents are all serializable.

The multimap is not threadsafe when any concurrent operations update the multimap, even if map and the instances generated by factory are. Concurrent read operations will work correctly. To allow concurrent update operations, wrap the multimap with a call to synchronizedMultimap.

Call this method only when the simpler methods ArrayListMultimap.create(), HashMultimap.create(), LinkedHashMultimap.create(), LinkedListMultimap.create(), TreeMultimap.create(), and TreeMultimap.create(Comparator, Comparator) won't suffice.

Note: the multimap assumes complete ownership over of map and the collections returned by factory. Those objects should not be manually updated and they should not use soft, weak, or phantom references.

Parameters:
map place to store the mapping from each key to its corresponding values
factory supplier of new, empty collections that will each hold all values for a given key
Throws:
IllegalArgumentException if map is not empty
 
   public static <K, V> Multimap<K, V> newMultimap(Map<K, Collection<V>> map,
       final Supplier<? extends Collection<V>> factory) {
     return new CustomMultimap<K, V>(mapfactory);
   }
 
   private static class CustomMultimap<K, V> extends AbstractMultimap<K, V> {
     transient Supplier<? extends Collection<V>> factory;
 
     CustomMultimap(Map<K, Collection<V>> map,
         Supplier<? extends Collection<V>> factory) {
       super(map);
       this. = checkNotNull(factory);
     }
 
     @Override protected Collection<V> createCollection() {
       return .get();
     }
 
     // can't use Serialization writeMultimap and populateMultimap methods since
     // there's no way to generate the empty backing map.
 
    

SerialData:
the factory and the backing map
 
     @GwtIncompatible("java.io.ObjectOutputStream")
     private void writeObject(ObjectOutputStream streamthrows IOException {
       stream.defaultWriteObject();
       stream.writeObject();
       stream.writeObject(backingMap());
     }
 
     @GwtIncompatible("java.io.ObjectInputStream")
     @SuppressWarnings("unchecked"// reading data stored by writeObject
     private void readObject(ObjectInputStream stream)
         throws IOExceptionClassNotFoundException {
       stream.defaultReadObject();
        = (Supplier<? extends Collection<V>>) stream.readObject();
       Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject();
       setMap(map);
     }
 
     @GwtIncompatible("java serialization not supported")
     private static final long serialVersionUID = 0;
   }

  
Creates a new ListMultimap that uses the provided map and factory. It can generate a multimap based on arbitrary Map and List classes.

The factory-generated and map classes determine the multimap iteration order. They also specify the behavior of the equals, hashCode, and toString methods for the multimap and its returned views. The multimap's get, removeAll, and replaceValues methods return RandomAccess lists if the factory does. However, the multimap's get method returns instances of a different class than does factory.get().

The multimap is serializable if map, factory, the lists generated by factory, and the multimap contents are all serializable.

The multimap is not threadsafe when any concurrent operations update the multimap, even if map and the instances generated by factory are. Concurrent read operations will work correctly. To allow concurrent update operations, wrap the multimap with a call to synchronizedListMultimap.

Call this method only when the simpler methods ArrayListMultimap.create() and LinkedListMultimap.create() won't suffice.

Note: the multimap assumes complete ownership over of map and the lists returned by factory. Those objects should not be manually updated, they should be empty when provided, and they should not use soft, weak, or phantom references.

Parameters:
map place to store the mapping from each key to its corresponding values
factory supplier of new, empty lists that will each hold all values for a given key
Throws:
IllegalArgumentException if map is not empty
 
   public static <K, V> ListMultimap<K, V> newListMultimap(
       Map<K, Collection<V>> mapfinal Supplier<? extends List<V>> factory) {
     return new CustomListMultimap<K, V>(mapfactory);
   }
 
   private static class CustomListMultimap<K, V>
       extends AbstractListMultimap<K, V> {
     transient Supplier<? extends List<V>> factory;
 
     CustomListMultimap(Map<K, Collection<V>> map,
         Supplier<? extends List<V>> factory) {
       super(map);
       this. = checkNotNull(factory);
     }
 
     @Override protected List<V> createCollection() {
       return .get();
     }

    

SerialData:
the factory and the backing map
 
     @GwtIncompatible("java.io.ObjectOutputStream")
     private void writeObject(ObjectOutputStream streamthrows IOException {
       stream.defaultWriteObject();
       stream.writeObject();
       stream.writeObject(backingMap());
     }
 
     @GwtIncompatible("java.io.ObjectInputStream")
     @SuppressWarnings("unchecked"// reading data stored by writeObject
     private void readObject(ObjectInputStream stream)
         throws IOExceptionClassNotFoundException {
       stream.defaultReadObject();
        = (Supplier<? extends List<V>>) stream.readObject();
       Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject();
       setMap(map);
     }
 
     @GwtIncompatible("java serialization not supported")
     private static final long serialVersionUID = 0;
   }

  
Creates a new SetMultimap that uses the provided map and factory. It can generate a multimap based on arbitrary Map and Set classes.

The factory-generated and map classes determine the multimap iteration order. They also specify the behavior of the equals, hashCode, and toString methods for the multimap and its returned views. However, the multimap's get method returns instances of a different class than factory.get() does.

The multimap is serializable if map, factory, the sets generated by factory, and the multimap contents are all serializable.

The multimap is not threadsafe when any concurrent operations update the multimap, even if map and the instances generated by factory are. Concurrent read operations will work correctly. To allow concurrent update operations, wrap the multimap with a call to synchronizedSetMultimap.

Call this method only when the simpler methods HashMultimap.create(), LinkedHashMultimap.create(), TreeMultimap.create(), and TreeMultimap.create(Comparator, Comparator) won't suffice.

Note: the multimap assumes complete ownership over of map and the sets returned by factory. Those objects should not be manually updated and they should not use soft, weak, or phantom references.

Parameters:
map place to store the mapping from each key to its corresponding values
factory supplier of new, empty sets that will each hold all values for a given key
Throws:
IllegalArgumentException if map is not empty
 
   public static <K, V> SetMultimap<K, V> newSetMultimap(
       Map<K, Collection<V>> mapfinal Supplier<? extends Set<V>> factory) {
     return new CustomSetMultimap<K, V>(mapfactory);
   }
 
   private static class CustomSetMultimap<K, V>
       extends AbstractSetMultimap<K, V> {
     transient Supplier<? extends Set<V>> factory;
 
     CustomSetMultimap(Map<K, Collection<V>> map,
         Supplier<? extends Set<V>> factory) {
       super(map);
       this. = checkNotNull(factory);
     }
 
     @Override protected Set<V> createCollection() {
       return .get();
     }

    

SerialData:
the factory and the backing map
 
     @GwtIncompatible("java.io.ObjectOutputStream")
     private void writeObject(ObjectOutputStream streamthrows IOException {
       stream.defaultWriteObject();
       stream.writeObject();
       stream.writeObject(backingMap());
     }
 
     @GwtIncompatible("java.io.ObjectInputStream")
     @SuppressWarnings("unchecked"// reading data stored by writeObject
     private void readObject(ObjectInputStream stream)
         throws IOExceptionClassNotFoundException {
       stream.defaultReadObject();
        = (Supplier<? extends Set<V>>) stream.readObject();
       Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject();
       setMap(map);
     }
 
     @GwtIncompatible("not needed in emulated source")
     private static final long serialVersionUID = 0;
   }

  
Creates a new SortedSetMultimap that uses the provided map and factory. It can generate a multimap based on arbitrary Map and SortedSet classes.

The factory-generated and map classes determine the multimap iteration order. They also specify the behavior of the equals, hashCode, and toString methods for the multimap and its returned views. However, the multimap's get method returns instances of a different class than factory.get() does.

The multimap is serializable if map, factory, the sets generated by factory, and the multimap contents are all serializable.

The multimap is not threadsafe when any concurrent operations update the multimap, even if map and the instances generated by factory are. Concurrent read operations will work correctly. To allow concurrent update operations, wrap the multimap with a call to synchronizedSortedSetMultimap.

Call this method only when the simpler methods TreeMultimap.create() and TreeMultimap.create(Comparator, Comparator) won't suffice.

Note: the multimap assumes complete ownership over of map and the sets returned by factory. Those objects should not be manually updated and they should not use soft, weak, or phantom references.

Parameters:
map place to store the mapping from each key to its corresponding values
factory supplier of new, empty sorted sets that will each hold all values for a given key
Throws:
IllegalArgumentException if map is not empty
 
   public static <K, V> SortedSetMultimap<K, V> newSortedSetMultimap(
       Map<K, Collection<V>> map,
       final Supplier<? extends SortedSet<V>> factory) {
     return new CustomSortedSetMultimap<K, V>(mapfactory);
   }
 
   private static class CustomSortedSetMultimap<K, V>
       extends AbstractSortedSetMultimap<K, V> {
     transient Supplier<? extends SortedSet<V>> factory;
     transient Comparator<? super V> valueComparator;
 
     CustomSortedSetMultimap(Map<K, Collection<V>> map,
         Supplier<? extends SortedSet<V>> factory) {
       super(map);
       this. = checkNotNull(factory);
        = factory.get().comparator();
     }
 
     @Override protected SortedSet<V> createCollection() {
       return .get();
     }
 
     @Override public Comparator<? super V> valueComparator() {
       return ;
     }

    

SerialData:
the factory and the backing map
 
     @GwtIncompatible("java.io.ObjectOutputStream")
     private void writeObject(ObjectOutputStream streamthrows IOException {
       stream.defaultWriteObject();
       stream.writeObject();
       stream.writeObject(backingMap());
     }
 
     @GwtIncompatible("java.io.ObjectInputStream")
     @SuppressWarnings("unchecked"// reading data stored by writeObject
     private void readObject(ObjectInputStream stream)
         throws IOExceptionClassNotFoundException {
       stream.defaultReadObject();
        = (Supplier<? extends SortedSet<V>>) stream.readObject();
        = .get().comparator();
       Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject();
       setMap(map);
     }
 
     @GwtIncompatible("not needed in emulated source")
     private static final long serialVersionUID = 0;
   }

  
Copies each key-value mapping in source into dest, with its key and value reversed.

If source is an ImmutableMultimap, consider using ImmutableMultimap.inverse instead.

Parameters:
source any multimap
dest the multimap to copy into; usually empty
Returns:
dest
 
   public static <K, V, M extends Multimap<K, V>> M invertFrom(
       Multimap<? extends V, ? extends K> source, M dest) {
     checkNotNull(dest);
     for (Map.Entry<? extends V, ? extends K> entry : source.entries()) {
       dest.put(entry.getValue(), entry.getKey());
     }
     return dest;
   }

  
Returns a synchronized (thread-safe) multimap backed by the specified multimap. In order to guarantee serial access, it is critical that all access to the backing multimap is accomplished through the returned multimap.

It is imperative that the user manually synchronize on the returned multimap when accessing any of its collection views:

   Multimap<K, V> multimap = Multimaps.synchronizedMultimap(
       HashMultimap.<K, V>create());
   ...
   Collection<V> values = multimap.get(key);  // Needn't be in synchronized block
   ...
   synchronized (multimap) {  // Synchronizing on multimap, not values!
     Iterator<V> i = values.iterator(); // Must be in synchronized block
     while (i.hasNext()) {
       foo(i.next());
     
   }}
Failure to follow this advice may result in non-deterministic behavior.

Note that the generated multimap's Multimap.removeAll and Multimap.replaceValues methods return collections that aren't synchronized.

The returned multimap will be serializable if the specified multimap is serializable.

Parameters:
multimap the multimap to be wrapped in a synchronized view
Returns:
a synchronized view of the specified multimap
 
   public static <K, V> Multimap<K, V> synchronizedMultimap(
       Multimap<K, V> multimap) {
     return Synchronized.multimap(multimapnull);
   }

  
Returns an unmodifiable view of the specified multimap. Query operations on the returned multimap "read through" to the specified multimap, and attempts to modify the returned multimap, either directly or through the multimap's views, result in an UnsupportedOperationException.

Note that the generated multimap's Multimap.removeAll and Multimap.replaceValues methods return collections that are modifiable.

The returned multimap will be serializable if the specified multimap is serializable.

Parameters:
delegate the multimap for which an unmodifiable view is to be returned
Returns:
an unmodifiable view of the specified multimap
 
   public static <K, V> Multimap<K, V> unmodifiableMultimap(
       Multimap<K, V> delegate) {
     if (delegate instanceof UnmodifiableMultimap ||
         delegate instanceof ImmutableMultimap) {
       return delegate;
     }
     return new UnmodifiableMultimap<K, V>(delegate);
   }

  
Simply returns its argument.

Deprecated:
no need to use this
Since:
10.0
 
   @Deprecated public static <K, V> Multimap<K, V> unmodifiableMultimap(
       ImmutableMultimap<K, V> delegate) {
     return checkNotNull(delegate);
   }
 
   private static class UnmodifiableMultimap<K, V>
       extends ForwardingMultimap<K, V> implements Serializable {
     final Multimap<K, V> delegate;
     transient Collection<Entry<K, V>> entries;
     transient Multiset<K> keys;
     transient Set<K> keySet;
     transient Collection<V> values;
     transient Map<K, Collection<V>> map;
 
     UnmodifiableMultimap(final Multimap<K, V> delegate) {
       this. = checkNotNull(delegate);
     }
 
     @Override protected Multimap<K, V> delegate() {
       return ;
     }
 
     @Override public void clear() {
       throw new UnsupportedOperationException();
     }
 
     @Override public Map<K, Collection<V>> asMap() {
       Map<K, Collection<V>> result = ;
       if (result == null) {
         final Map<K, Collection<V>> unmodifiableMap
             = Collections.unmodifiableMap(.asMap());
          = result = new ForwardingMap<K, Collection<V>>() {
           @Override protected Map<K, Collection<V>> delegate() {
             return unmodifiableMap;
           }
 
           Set<Entry<K, Collection<V>>> entrySet;
 
           @Override public Set<Map.Entry<K, Collection<V>>> entrySet() {
             Set<Entry<K, Collection<V>>> result = ;
             return (result == null)
                 ? 
                     = unmodifiableAsMapEntries(unmodifiableMap.entrySet())
                 : result;
           }
 
           @Override public Collection<V> get(Object key) {
             Collection<V> collection = unmodifiableMap.get(key);
             return (collection == null)
                 ? null : unmodifiableValueCollection(collection);
           }
 
           Collection<Collection<V>> asMapValues;
 
           @Override public Collection<Collection<V>> values() {
             Collection<Collection<V>> result = ;
             return (result == null)
                 ? 
                     = new UnmodifiableAsMapValues<V>(unmodifiableMap.values())
                 : result;
           }
 
           @Override public boolean containsValue(Object o) {
             return values().contains(o);
           }
         };
       }
       return result;
     }
 
     @Override public Collection<Entry<K, V>> entries() {
       Collection<Entry<K, V>> result = ;
       if (result == null) {
          = result = unmodifiableEntries(.entries());
       }
       return result;
     }
 
     @Override public Collection<V> get(K key) {
       return unmodifiableValueCollection(.get(key));
     }
 
     @Override public Multiset<K> keys() {
       Multiset<K> result = ;
       if (result == null) {
          = result = Multisets.unmodifiableMultiset(.keys());
       }
       return result;
     }
 
     @Override public Set<K> keySet() {
       Set<K> result = ;
       if (result == null) {
          = result = Collections.unmodifiableSet(.keySet());
       }
       return result;
     }
 
     @Override public boolean put(K key, V value) {
       throw new UnsupportedOperationException();
     }
 
     @Override public boolean putAll(K keyIterable<? extends V> values) {
       throw new UnsupportedOperationException();
     }
 
     @Override
     public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
       throw new UnsupportedOperationException();
     }
 
     @Override public boolean remove(Object keyObject value) {
       throw new UnsupportedOperationException();
     }
 
     @Override public Collection<V> removeAll(Object key) {
       throw new UnsupportedOperationException();
     }
 
     @Override public Collection<V> replaceValues(
         K keyIterable<? extends V> values) {
       throw new UnsupportedOperationException();
     }
 
     @Override public Collection<V> values() {
       Collection<V> result = ;
       if (result == null) {
          = result = Collections.unmodifiableCollection(.values());
       }
       return result;
     }
 
     private static final long serialVersionUID = 0;
   }
 
   private static class UnmodifiableAsMapValues<V>
       extends ForwardingCollection<Collection<V>> {
     final Collection<Collection<V>> delegate;
       this. = Collections.unmodifiableCollection(delegate);
     }
     @Override protected Collection<Collection<V>> delegate() {
       return ;
     }
     @Override public Iterator<Collection<V>> iterator() {
       final Iterator<Collection<V>> iterator = .iterator();
       return new UnmodifiableIterator<Collection<V>>() {
         @Override
         public boolean hasNext() {
           return iterator.hasNext();
         }
         @Override
         public Collection<V> next() {
           return unmodifiableValueCollection(iterator.next());
         }
       };
     }
     @Override public Object[] toArray() {
       return standardToArray();
     }
     @Override public <T> T[] toArray(T[] array) {
       return standardToArray(array);
     }
     @Override public boolean contains(Object o) {
       return standardContains(o);
     }
     @Override public boolean containsAll(Collection<?> c) {
       return standardContainsAll(c);
     }
   }
 
   private static class UnmodifiableListMultimap<K, V>
       extends UnmodifiableMultimap<K, V> implements ListMultimap<K, V> {
     UnmodifiableListMultimap(ListMultimap<K, V> delegate) {
       super(delegate);
     }
     @Override public ListMultimap<K, V> delegate() {
       return (ListMultimap<K, V>) super.delegate();
     }
     @Override public List<V> get(K key) {
       return Collections.unmodifiableList(delegate().get(key));
     }
     @Override public List<V> removeAll(Object key) {
       throw new UnsupportedOperationException();
     }
     @Override public List<V> replaceValues(
         K keyIterable<? extends V> values) {
       throw new UnsupportedOperationException();
     }
     private static final long serialVersionUID = 0;
   }
 
   private static class UnmodifiableSetMultimap<K, V>
       extends UnmodifiableMultimap<K, V> implements SetMultimap<K, V> {
     UnmodifiableSetMultimap(SetMultimap<K, V> delegate) {
       super(delegate);
     }
     @Override public SetMultimap<K, V> delegate() {
       return (SetMultimap<K, V>) super.delegate();
     }
     @Override public Set<V> get(K key) {
       /*
        * Note that this doesn't return a SortedSet when delegate is a
        * SortedSetMultiset, unlike (SortedSet<V>) super.get().
        */
       return Collections.unmodifiableSet(delegate().get(key));
     }
     @Override public Set<Map.Entry<K, V>> entries() {
       return Maps.unmodifiableEntrySet(delegate().entries());
     }
     @Override public Set<V> removeAll(Object key) {
       throw new UnsupportedOperationException();
     }
     @Override public Set<V> replaceValues(
         K keyIterable<? extends V> values) {
       throw new UnsupportedOperationException();
     }
     private static final long serialVersionUID = 0;
   }
 
   private static class UnmodifiableSortedSetMultimap<K, V>
       extends UnmodifiableSetMultimap<K, V> implements SortedSetMultimap<K, V> {
       super(delegate);
     }
     @Override public SortedSetMultimap<K, V> delegate() {
       return (SortedSetMultimap<K, V>) super.delegate();
     }
     @Override public SortedSet<V> get(K key) {
       return Collections.unmodifiableSortedSet(delegate().get(key));
     }
     @Override public SortedSet<V> removeAll(Object key) {
       throw new UnsupportedOperationException();
     }
     @Override public SortedSet<V> replaceValues(
         K keyIterable<? extends V> values) {
       throw new UnsupportedOperationException();
     }
     @Override
     public Comparator<? super V> valueComparator() {
       return delegate().valueComparator();
     }
     private static final long serialVersionUID = 0;
   }

  
Returns a synchronized (thread-safe) SetMultimap backed by the specified multimap.

You must follow the warnings described in synchronizedMultimap.

The returned multimap will be serializable if the specified multimap is serializable.

Parameters:
multimap the multimap to be wrapped
Returns:
a synchronized view of the specified multimap
 
   public static <K, V> SetMultimap<K, V> synchronizedSetMultimap(
       SetMultimap<K, V> multimap) {
     return Synchronized.setMultimap(multimapnull);
   }

  
Returns an unmodifiable view of the specified SetMultimap. Query operations on the returned multimap "read through" to the specified multimap, and attempts to modify the returned multimap, either directly or through the multimap's views, result in an UnsupportedOperationException.

Note that the generated multimap's Multimap.removeAll and Multimap.replaceValues methods return collections that are modifiable.

The returned multimap will be serializable if the specified multimap is serializable.

Parameters:
delegate the multimap for which an unmodifiable view is to be returned
Returns:
an unmodifiable view of the specified multimap
 
   public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(
       SetMultimap<K, V> delegate) {
     if (delegate instanceof UnmodifiableSetMultimap ||
         delegate instanceof ImmutableSetMultimap) {
       return delegate;
     }
     return new UnmodifiableSetMultimap<K, V>(delegate);
   }

  
Simply returns its argument.

Deprecated:
no need to use this
Since:
10.0
 
   @Deprecated public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(
       ImmutableSetMultimap<K, V> delegate) {
     return checkNotNull(delegate);
   }

  
Returns a synchronized (thread-safe) SortedSetMultimap backed by the specified multimap.

You must follow the warnings described in synchronizedMultimap.

The returned multimap will be serializable if the specified multimap is serializable.

Parameters:
multimap the multimap to be wrapped
Returns:
a synchronized view of the specified multimap
 
   public static <K, V> SortedSetMultimap<K, V>
       synchronizedSortedSetMultimap(SortedSetMultimap<K, V> multimap) {
     return Synchronized.sortedSetMultimap(multimapnull);
   }

  
Returns an unmodifiable view of the specified SortedSetMultimap. Query operations on the returned multimap "read through" to the specified multimap, and attempts to modify the returned multimap, either directly or through the multimap's views, result in an UnsupportedOperationException.

Note that the generated multimap's Multimap.removeAll and Multimap.replaceValues methods return collections that are modifiable.

The returned multimap will be serializable if the specified multimap is serializable.

Parameters:
delegate the multimap for which an unmodifiable view is to be returned
Returns:
an unmodifiable view of the specified multimap
 
   public static <K, V> SortedSetMultimap<K, V> unmodifiableSortedSetMultimap(
       SortedSetMultimap<K, V> delegate) {
     if (delegate instanceof UnmodifiableSortedSetMultimap) {
       return delegate;
     }
     return new UnmodifiableSortedSetMultimap<K, V>(delegate);
   }

  
Returns a synchronized (thread-safe) ListMultimap backed by the specified multimap.

You must follow the warnings described in synchronizedMultimap.

Parameters:
multimap the multimap to be wrapped
Returns:
a synchronized view of the specified multimap
 
   public static <K, V> ListMultimap<K, V> synchronizedListMultimap(
       ListMultimap<K, V> multimap) {
     return Synchronized.listMultimap(multimapnull);
   }

  
Returns an unmodifiable view of the specified ListMultimap. Query operations on the returned multimap "read through" to the specified multimap, and attempts to modify the returned multimap, either directly or through the multimap's views, result in an UnsupportedOperationException.

Note that the generated multimap's Multimap.removeAll and Multimap.replaceValues methods return collections that are modifiable.

The returned multimap will be serializable if the specified multimap is serializable.

Parameters:
delegate the multimap for which an unmodifiable view is to be returned
Returns:
an unmodifiable view of the specified multimap
 
   public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(
       ListMultimap<K, V> delegate) {
     if (delegate instanceof UnmodifiableListMultimap ||
         delegate instanceof ImmutableListMultimap) {
       return delegate;
     }
     return new UnmodifiableListMultimap<K, V>(delegate);
   }

  
Simply returns its argument.

Deprecated:
no need to use this
Since:
10.0
 
   @Deprecated public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(
       ImmutableListMultimap<K, V> delegate) {
     return checkNotNull(delegate);
   }

  
Returns an unmodifiable view of the specified collection, preserving the interface for instances of SortedSet, Set, List and Collection, in that order of preference.

Parameters:
collection the collection for which to return an unmodifiable view
Returns:
an unmodifiable view of the collection
 
   private static <V> Collection<V> unmodifiableValueCollection(
       Collection<V> collection) {
     if (collection instanceof SortedSet) {
       return Collections.unmodifiableSortedSet((SortedSet<V>) collection);
     } else if (collection instanceof Set) {
       return Collections.unmodifiableSet((Set<V>) collection);
     } else if (collection instanceof List) {
       return Collections.unmodifiableList((List<V>) collection);
     }
     return Collections.unmodifiableCollection(collection);
   }

  
Returns an unmodifiable view of the specified multimap asMap entry. The Entry.setValue operation throws an UnsupportedOperationException, and the collection returned by getValue is also an unmodifiable (type-preserving) view. This also has the side-effect of redefining equals to comply with the Map.Entry contract, and to avoid a possible nefarious implementation of equals.

Parameters:
entry the entry for which to return an unmodifiable view
Returns:
an unmodifiable view of the entry
 
   private static <K, V> Map.Entry<K, Collection<V>> unmodifiableAsMapEntry(
       final Map.Entry<K, Collection<V>> entry) {
     checkNotNull(entry);
     return new AbstractMapEntry<K, Collection<V>>() {
       @Override public K getKey() {
         return entry.getKey();
       }
 
       @Override public Collection<V> getValue() {
         return unmodifiableValueCollection(entry.getValue());
       }
     };
   }

  
Returns an unmodifiable view of the specified collection of entries. The Entry.setValue operation throws an UnsupportedOperationException. If the specified collection is a Set, the returned collection is also a Set.

Parameters:
entries the entries for which to return an unmodifiable view
Returns:
an unmodifiable view of the entries
 
   private static <K, V> Collection<Entry<K, V>> unmodifiableEntries(
       Collection<Entry<K, V>> entries) {
     if (entries instanceof Set) {
       return Maps.unmodifiableEntrySet((Set<Entry<K, V>>) entries);
     }
     return new Maps.UnmodifiableEntries<K, V>(
         Collections.unmodifiableCollection(entries));
   }

  
Returns an unmodifiable view of the specified set of asMap entries. The Entry.setValue operation throws an UnsupportedOperationException, as do any operations that attempt to modify the returned collection.

Parameters:
asMapEntries the asMap entries for which to return an unmodifiable view
Returns:
an unmodifiable view of the collection entries
 
   private static <K, V> Set<Entry<K, Collection<V>>> unmodifiableAsMapEntries(
       Set<Entry<K, Collection<V>>> asMapEntries) {
     return new UnmodifiableAsMapEntries<K, V>(
         Collections.unmodifiableSet(asMapEntries));
   }

  

See also:
Multimaps.unmodifiableAsMapEntries
 
   static class UnmodifiableAsMapEntries<K, V>
       extends ForwardingSet<Entry<K, Collection<V>>> {
     private final Set<Entry<K, Collection<V>>> delegate;
     UnmodifiableAsMapEntries(Set<Entry<K, Collection<V>>> delegate) {
       this. = delegate;
     }
 
     @Override protected Set<Entry<K, Collection<V>>> delegate() {
       return ;
     }
 
     @Override public Iterator<Entry<K, Collection<V>>> iterator() {
       final Iterator<Entry<K, Collection<V>>> iterator = .iterator();
       return new ForwardingIterator<Entry<K, Collection<V>>>() {
         @Override protected Iterator<Entry<K, Collection<V>>> delegate() {
           return iterator;
         }
         @Override public Entry<K, Collection<V>> next() {
           return unmodifiableAsMapEntry(iterator.next());
         }
       };
     }
 
     @Override public Object[] toArray() {
       return standardToArray();
     }
 
     @Override public <T> T[] toArray(T[] array) {
       return standardToArray(array);
     }
 
     @Override public boolean contains(Object o) {
       return Maps.containsEntryImpl(delegate(), o);
     }
 
     @Override public boolean containsAll(Collection<?> c) {
       return standardContainsAll(c);
     }
 
     @Override public boolean equals(@Nullable Object object) {
       return standardEquals(object);
    }
  }

  
Returns a multimap view of the specified map. The multimap is backed by the map, so changes to the map are reflected in the multimap, and vice versa. If the map is modified while an iteration over one of the multimap's collection views is in progress (except through the iterator's own remove operation, or through the setValue operation on a map entry returned by the iterator), the results of the iteration are undefined.

The multimap supports mapping removal, which removes the corresponding mapping from the map. It does not support any operations which might add mappings, such as put, putAll or replaceValues.

The returned multimap will be serializable if the specified map is serializable.

Parameters:
map the backing map for the returned multimap view
  public static <K, V> SetMultimap<K, V> forMap(Map<K, V> map) {
    return new MapMultimap<K, V>(map);
  }

  

See also:
Multimaps.forMap
  private static class MapMultimap<K, V>
      implements SetMultimap<K, V>, Serializable {
    final Map<K, V> map;
    transient Map<K, Collection<V>> asMap;
    MapMultimap(Map<K, V> map) {
      this. = checkNotNull(map);
    }
    @Override
    public int size() {
      return .size();
    }
    @Override
    public boolean isEmpty() {
      return .isEmpty();
    }
    @Override
    public boolean containsKey(Object key) {
      return .containsKey(key);
    }
    @Override
    public boolean containsValue(Object value) {
      return .containsValue(value);
    }
    @Override
    public boolean containsEntry(Object keyObject value) {
      return .entrySet().contains(Maps.immutableEntry(keyvalue));
    }
    @Override
    public Set<V> get(final K key) {
      return new Sets.ImprovedAbstractSet<V>() {
        @Override public Iterator<V> iterator() {
          return new Iterator<V>() {
            int i;
            @Override
            public boolean hasNext() {
              return ( == 0) && .containsKey(key);
            }
            @Override
            public V next() {
              if (!hasNext()) {
                throw new NoSuchElementException();
              }
              ++;
              return .get(key);
            }
            @Override
            public void remove() {
              checkState( == 1);
               = -1;
              .remove(key);
            }
          };
        }
        @Override public int size() {
          return .containsKey(key) ? 1 : 0;
        }
      };
    }
    @Override
    public boolean put(K key, V value) {
      throw new UnsupportedOperationException();
    }
    @Override
    public boolean putAll(K keyIterable<? extends V> values) {
      throw new UnsupportedOperationException();
    }
    @Override
    public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
      throw new UnsupportedOperationException();
    }
    @Override
    public Set<V> replaceValues(K keyIterable<? extends V> values) {
      throw new UnsupportedOperationException();
    }
    @Override
    public boolean remove(Object keyObject value) {
      return .entrySet().remove(Maps.immutableEntry(keyvalue));
    }
    @Override
    public Set<V> removeAll(Object key) {
      Set<V> values = new HashSet<V>(2);
      if (!.containsKey(key)) {
        return values;
      }
      values.add(.remove(key));
      return values;
    }
    @Override
    public void clear() {
      .clear();
    }
    @Override
    public Set<K> keySet() {
      return .keySet();
    }
    @Override
    public Multiset<K> keys() {
      return Multisets.forSet(.keySet());
    }
    @Override
    public Collection<V> values() {
      return .values();
    }
    @Override
    public Set<Entry<K, V>> entries() {
      return .entrySet();
    }
    @Override
    public Map<K, Collection<V>> asMap() {
      Map<K, Collection<V>> result = ;
      if (result == null) {
         = result = new AsMap();
      }
      return result;
    }
    @Override public boolean equals(@Nullable Object object) {
      if (object == this) {
        return true;
      }
      if (object instanceof Multimap) {
        Multimap<?, ?> that = (Multimap<?, ?>) object;
        return this.size() == that.size() && asMap().equals(that.asMap());
      }
      return false;
    }
    @Override public int hashCode() {
      return .hashCode();
    }
    private static final MapJoiner JOINER
        = Joiner.on("], ").withKeyValueSeparator("=[").useForNull("null");
    @Override public String toString() {
      if (.isEmpty()) {
        return "{}";
      }
      StringBuilder builder
          = Collections2.newStringBuilderForCollection(.size()).append('{');
      .appendTo(builder);
      return builder.append("]}").toString();
    }

    

See also:
MapMultimap.asMap
    class AsMapEntries extends Sets.ImprovedAbstractSet<Entry<K, Collection<V>>> {
      @Override public int size() {
        return .size();
      }
      @Override public Iterator<Entry<K, Collection<V>>> iterator() {
        return new TransformedIterator<K, Entry<K, Collection<V>>>(.keySet().iterator()) {
          @Override
          Entry<K, Collection<V>> transform(final K key) {
            return new AbstractMapEntry<K, Collection<V>>() {
              @Override
              public K getKey() {
                return key;
              }
              @Override
              public Collection<V> getValue() {
                return get(key);
              }
            };
          }
        };
      }
      @Override public boolean contains(Object o) {
        if (!(o instanceof Entry)) {
          return false;
        }
        Entry<?, ?> entry = (Entry<?, ?>) o;
        if (!(entry.getValue() instanceof Set)) {
          return false;
        }
        Set<?> set = (Set<?>) entry.getValue();
        return (set.size() == 1)
            && containsEntry(entry.getKey(), set.iterator().next());
      }
      @Override public boolean remove(Object o) {
        if (!(o instanceof Entry)) {
          return false;
        }
        Entry<?, ?> entry = (Entry<?, ?>) o;
        if (!(entry.getValue() instanceof Set)) {
          return false;
        }
        Set<?> set = (Set<?>) entry.getValue();
        return (set.size() == 1)
            && .entrySet().remove(
                Maps.immutableEntry(entry.getKey(), set.iterator().next()));
      }
    }

    

See also:
MapMultimap.asMap
    class AsMap extends Maps.ImprovedAbstractMap<K, Collection<V>> {
      @Override protected Set<Entry<K, Collection<V>>> createEntrySet() {
        return new AsMapEntries();
      }
      // The following methods are included for performance.
      @Override public boolean containsKey(Object key) {
        return .containsKey(key);
      }
      @SuppressWarnings("unchecked")
      @Override public Collection<V> get(Object key) {
        Collection<V> collection = MapMultimap.this.get((K) key);
        return collection.isEmpty() ? null : collection;
      }
      @Override public Collection<V> remove(Object key) {
        Collection<V> collection = removeAll(key);
        return collection.isEmpty() ? null : collection;
      }
    }
    private static final long serialVersionUID = 7845222491160860175L;
  }

  
Returns a view of a multimap where each value is transformed by a function. All other properties of the multimap, such as iteration order, are left intact. For example, the code:
   Multimap<String, Integer> multimap =
     ImmutableSetMultimap.of("a", 2, "b", -3, "b", -3, "a", 4, "c", 6);
 Function<Integer, String> square = new Function<Integer, String>() {
     public String apply(Integer in) {
       return Integer.toString(in * in);
     
 };
 Multimap<String, String> transformed =
     Multimaps.transformValues(multimap, square);
   System.out.println(transformed);}
... prints {a=[4, 16], b=[9, 9], c=[6]}.

Changes in the underlying multimap are reflected in this view. Conversely, this view supports removal operations, and these are reflected in the underlying multimap.

It's acceptable for the underlying multimap to contain null keys, and even null values provided that the function is capable of accepting null input. The transformed multimap might contain null values, if the function sometimes gives a null result.

The returned multimap is not thread-safe or serializable, even if the underlying multimap is. The equals and hashCode methods of the returned multimap are meaningless, since there is not a definition of equals or hashCode for general collections, and get() will return a general Collection as opposed to a List or a Set.

The function is applied lazily, invoked when needed. This is necessary for the returned multimap to be a view, but it means that the function will be applied many times for bulk operations like Multimap.containsValue and Multimap.toString(). For this to perform well, function should be fast. To avoid lazy evaluation when the returned multimap doesn't need to be a view, copy the returned multimap into a new multimap of your choosing.

Since:
7.0
  public static <K, V1, V2> Multimap<K, V2> transformValues(
      Multimap<K, V1> fromMultimapfinal Function<? super V1, V2> function) {
    checkNotNull(function);
    EntryTransformer<K, V1, V2> transformer =
        new EntryTransformer<K, V1, V2>() {
          @Override
          public V2 transformEntry(K key, V1 value) {
            return function.apply(value);
          }
        };
    return transformEntries(fromMultimaptransformer);
  }

  
Returns a view of a multimap whose values are derived from the original multimap's entries. In contrast to transformValues, this method's entry-transformation logic may depend on the key as well as the value.

All other properties of the transformed multimap, such as iteration order, are left intact. For example, the code:

   SetMultimap<String, Integer> multimap =
       ImmutableSetMultimap.of("a", 1, "a", 4, "b", -6);
   EntryTransformer<String, Integer, String> transformer =
       new EntryTransformer<String, Integer, String>() {
         public String transformEntry(String key, Integer value) {
            return (value >= 0) ? key : "no" + key;
         
       };
   Multimap<String, String> transformed =
       Multimaps.transformEntries(multimap, transformer);
   System.out.println(transformed);}
... prints {a=[a, a], b=[nob]}.

Changes in the underlying multimap are reflected in this view. Conversely, this view supports removal operations, and these are reflected in the underlying multimap.

It's acceptable for the underlying multimap to contain null keys and null values provided that the transformer is capable of accepting null inputs. The transformed multimap might contain null values if the transformer sometimes gives a null result.

The returned multimap is not thread-safe or serializable, even if the underlying multimap is. The equals and hashCode methods of the returned multimap are meaningless, since there is not a definition of equals or hashCode for general collections, and get() will return a general Collection as opposed to a List or a Set.

The transformer is applied lazily, invoked when needed. This is necessary for the returned multimap to be a view, but it means that the transformer will be applied many times for bulk operations like Multimap.containsValue and Object.toString. For this to perform well, transformer should be fast. To avoid lazy evaluation when the returned multimap doesn't need to be a view, copy the returned multimap into a new multimap of your choosing.

Warning: This method assumes that for any instance k of EntryTransformer key type K, k.equals(k2) implies that k2 is also of type K. Using an EntryTransformer key type for which this may not hold, such as ArrayList, may risk a ClassCastException when calling methods on the transformed multimap.

Since:
7.0
  public static <K, V1, V2> Multimap<K, V2> transformEntries(
      Multimap<K, V1> fromMap,
      EntryTransformer<? super K, ? super V1, V2> transformer) {
    return new TransformedEntriesMultimap<K, V1, V2>(fromMaptransformer);
  }
  private static class TransformedEntriesMultimap<K, V1, V2>
      implements Multimap<K, V2> {
    final Multimap<K, V1> fromMultimap;
    final EntryTransformer<? super K, ? super V1, V2> transformer;
    TransformedEntriesMultimap(Multimap<K, V1> fromMultimap,
        final EntryTransformer<? super K, ? super V1, V2> transformer) {
      this. = checkNotNull(fromMultimap);
      this. = checkNotNull(transformer);
    }
    Collection<V2> transform(final K keyCollection<V1> values) {
      return Collections2.transform(valuesnew Function<V1, V2>() {
        @Override public V2 apply(V1 value) {
          return .transformEntry(keyvalue);
        }
      });
    }
    private transient Map<K, Collection<V2>> asMap;
    @Override public Map<K, Collection<V2>> asMap() {
      if ( == null) {
        Map<K, Collection<V2>> aM = Maps.transformEntries(.asMap(),
            new EntryTransformer<K, Collection<V1>, Collection<V2>>() {
              @Override public Collection<V2> transformEntry(
                  K keyCollection<V1> value) {
                return transform(keyvalue);
              }
            });
         = aM;
        return aM;
      }
      return ;
    }
    @Override public void clear() {
      .clear();
    }
    @SuppressWarnings("unchecked")
    @Override public boolean containsEntry(Object keyObject value) {
      Collection<V2> values = get((K) key);
      return values.contains(value);
    }