Home | History | Annotate | Download | only in collect
      1 /*
      2  * Copyright (C) 2007 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.common.collect;
     18 
     19 import com.google.common.annotations.GwtCompatible;
     20 import static com.google.common.base.Preconditions.checkNotNull;
     21 
     22 import java.io.IOException;
     23 import java.io.ObjectInputStream;
     24 import java.io.ObjectOutputStream;
     25 import java.util.Collection;
     26 import java.util.Comparator;
     27 import java.util.Set;
     28 import java.util.SortedMap;
     29 import java.util.SortedSet;
     30 import java.util.TreeMap;
     31 import java.util.TreeSet;
     32 
     33 import javax.annotation.Nullable;
     34 
     35 /**
     36  * Implementation of {@code Multimap} whose keys and values are ordered by
     37  * their natural ordering or by supplied comparators. In all cases, this
     38  * implementation uses {@link Comparable#compareTo} or {@link
     39  * Comparator#compare} instead of {@link Object#equals} to determine
     40  * equivalence of instances.
     41  *
     42  * <p><b>Warning:</b> The comparators or comparables used must be <i>consistent
     43  * with equals</i> as explained by the {@link Comparable} class specification.
     44  * Otherwise, the resulting multiset will violate the general contract of {@link
     45  * SetMultimap}, which it is specified in terms of {@link Object#equals}.
     46  *
     47  * <p>The collections returned by {@code keySet} and {@code asMap} iterate
     48  * through the keys according to the key comparator ordering or the natural
     49  * ordering of the keys. Similarly, {@code get}, {@code removeAll}, and {@code
     50  * replaceValues} return collections that iterate through the values according
     51  * to the value comparator ordering or the natural ordering of the values. The
     52  * collections generated by {@code entries}, {@code keys}, and {@code values}
     53  * iterate across the keys according to the above key ordering, and for each
     54  * key they iterate across the values according to the value ordering.
     55  *
     56  * <p>The multimap does not store duplicate key-value pairs. Adding a new
     57  * key-value pair equal to an existing key-value pair has no effect.
     58  *
     59  * <p>Depending on the comparators, null keys and values may or may not be
     60  * supported. The natural ordering does not support nulls. All optional multimap
     61  * methods are supported, and all returned views are modifiable.
     62  *
     63  * <p>This class is not threadsafe when any concurrent operations update the
     64  * multimap. Concurrent read operations will work correctly. To allow concurrent
     65  * update operations, wrap your multimap with a call to {@link
     66  * Multimaps#synchronizedSortedSetMultimap}.
     67  *
     68  * @author Jared Levy
     69  * @since 2010.01.04 <b>stable</b> (imported from Google Collections Library)
     70  */
     71 @GwtCompatible(serializable = true)
     72 public class TreeMultimap<K, V> extends AbstractSortedSetMultimap<K, V> {
     73   private transient Comparator<? super K> keyComparator;
     74   private transient Comparator<? super V> valueComparator;
     75 
     76   /**
     77    * Creates an empty {@code TreeMultimap} ordered by the natural ordering of
     78    * its keys and values.
     79    */
     80   @SuppressWarnings("unchecked") // eclipse doesn't like the raw Comparable
     81   public static <K extends Comparable, V extends Comparable>
     82       TreeMultimap<K, V> create() {
     83     return new TreeMultimap<K, V>(Ordering.natural(), Ordering.natural());
     84   }
     85 
     86   /**
     87    * Creates an empty {@code TreeMultimap} instance using explicit comparators.
     88    * Neither comparator may be null; use {@link Ordering#natural()} to specify
     89    * natural order.
     90    *
     91    * @param keyComparator the comparator that determines the key ordering
     92    * @param valueComparator the comparator that determines the value ordering
     93    */
     94   public static <K, V> TreeMultimap<K, V> create(
     95       Comparator<? super K> keyComparator,
     96       Comparator<? super V> valueComparator) {
     97     return new TreeMultimap<K, V>(checkNotNull(keyComparator),
     98         checkNotNull(valueComparator));
     99   }
    100 
    101   /**
    102    * Constructs a {@code TreeMultimap}, ordered by the natural ordering of its
    103    * keys and values, with the same mappings as the specified multimap.
    104    *
    105    * @param multimap the multimap whose contents are copied to this multimap
    106    */
    107   @SuppressWarnings("unchecked") // eclipse doesn't like the raw Comparable
    108   public static <K extends Comparable, V extends Comparable>
    109       TreeMultimap<K, V> create(Multimap<? extends K, ? extends V> multimap) {
    110     return new TreeMultimap<K, V>(Ordering.natural(), Ordering.natural(),
    111         multimap);
    112   }
    113 
    114   // Used by the TreeMultimap serialization test.
    115   TreeMultimap() {
    116     this(null, null);
    117   }
    118 
    119   // Must be package-private so multimaps with null comparators can be
    120   // serialized (which can be created with Multimaps.newTreeMultimap()). Once
    121   // that method is removed, this constructor can be made private.
    122   TreeMultimap(@Nullable Comparator<? super K> keyComparator,
    123       @Nullable Comparator<? super V> valueComparator) {
    124     super((keyComparator == null)
    125         ? new TreeMap<K, Collection<V>>()
    126         : new TreeMap<K, Collection<V>>(keyComparator));
    127     this.keyComparator = keyComparator;
    128     this.valueComparator = valueComparator;
    129   }
    130 
    131   private TreeMultimap(Comparator<? super K> keyComparator,
    132       Comparator<? super V> valueComparator,
    133       Multimap<? extends K, ? extends V> multimap) {
    134     this(keyComparator, valueComparator);
    135     putAll(multimap);
    136   }
    137 
    138   /**
    139    * {@inheritDoc}
    140    *
    141    * <p>Creates an empty {@code TreeSet} for a collection of values for one key.
    142    *
    143    * @return a new {@code TreeSet} containing a collection of values for one
    144    *     key
    145    */
    146   @Override SortedSet<V> createCollection() {
    147     return (valueComparator == null)
    148         ? new TreeSet<V>() : new TreeSet<V>(valueComparator);
    149   }
    150 
    151   /**
    152    * Returns the comparator that orders the multimap keys.
    153    */
    154   public Comparator<? super K> keyComparator() {
    155     return keyComparator;
    156   }
    157 
    158   public Comparator<? super V> valueComparator() {
    159     return valueComparator;
    160   }
    161 
    162   /**
    163    * {@inheritDoc}
    164    *
    165    * <p>Because a {@code TreeMultimap} has unique sorted keys, this method
    166    * returns a {@link SortedSet}, instead of the {@link Set} specified in the
    167    * {@link Multimap} interface.
    168    */
    169   @Override public SortedSet<K> keySet() {
    170     return (SortedSet<K>) super.keySet();
    171   }
    172 
    173   /**
    174    * {@inheritDoc}
    175    *
    176    * <p>Because a {@code TreeMultimap} has unique sorted keys, this method
    177    * returns a {@link SortedMap}, instead of the {@link java.util.Map} specified
    178    * in the {@link Multimap} interface.
    179    */
    180   @Override public SortedMap<K, Collection<V>> asMap() {
    181     return (SortedMap<K, Collection<V>>) super.asMap();
    182   }
    183 
    184   /**
    185    * @serialData key comparator, value comparator, number of distinct keys, and
    186    *     then for each distinct key: the key, number of values for that key, and
    187    *     key values
    188    */
    189   private void writeObject(ObjectOutputStream stream) throws IOException {
    190     stream.defaultWriteObject();
    191     stream.writeObject(keyComparator());
    192     stream.writeObject(valueComparator());
    193     Serialization.writeMultimap(this, stream);
    194   }
    195 
    196   @SuppressWarnings("unchecked") // reading data stored by writeObject
    197   private void readObject(ObjectInputStream stream)
    198       throws IOException, ClassNotFoundException {
    199     stream.defaultReadObject();
    200     keyComparator = (Comparator<? super K>) stream.readObject();
    201     valueComparator = (Comparator<? super V>) stream.readObject();
    202     setMap(new TreeMap<K, Collection<V>>(keyComparator));
    203     Serialization.populateMultimap(this, stream);
    204   }
    205 
    206   private static final long serialVersionUID = 0;
    207 }
    208