Home | History | Annotate | Download | only in collect
      1 /*
      2  * Copyright (C) 2007 The Guava Authors
      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 static com.google.common.base.Preconditions.checkArgument;
     20 import static com.google.common.base.Preconditions.checkNotNull;
     21 import static com.google.common.collect.CollectPreconditions.checkNonnegative;
     22 import static com.google.common.collect.CollectPreconditions.checkRemove;
     23 
     24 import com.google.common.annotations.Beta;
     25 import com.google.common.annotations.GwtCompatible;
     26 import com.google.common.base.Objects;
     27 import com.google.common.base.Predicate;
     28 import com.google.common.base.Predicates;
     29 import com.google.common.collect.Multiset.Entry;
     30 import com.google.common.primitives.Ints;
     31 
     32 import java.io.Serializable;
     33 import java.util.Collection;
     34 import java.util.Collections;
     35 import java.util.Iterator;
     36 import java.util.List;
     37 import java.util.NoSuchElementException;
     38 import java.util.Set;
     39 
     40 import javax.annotation.Nullable;
     41 
     42 /**
     43  * Provides static utility methods for creating and working with {@link
     44  * Multiset} instances.
     45  *
     46  * <p>See the Guava User Guide article on <a href=
     47  * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Multisets">
     48  * {@code Multisets}</a>.
     49  *
     50  * @author Kevin Bourrillion
     51  * @author Mike Bostock
     52  * @author Louis Wasserman
     53  * @since 2.0 (imported from Google Collections Library)
     54  */
     55 @GwtCompatible
     56 public final class Multisets {
     57   private Multisets() {}
     58 
     59   /**
     60    * Returns an unmodifiable view of the specified multiset. Query operations on
     61    * the returned multiset "read through" to the specified multiset, and
     62    * attempts to modify the returned multiset result in an
     63    * {@link UnsupportedOperationException}.
     64    *
     65    * <p>The returned multiset will be serializable if the specified multiset is
     66    * serializable.
     67    *
     68    * @param multiset the multiset for which an unmodifiable view is to be
     69    *     generated
     70    * @return an unmodifiable view of the multiset
     71    */
     72   public static <E> Multiset<E> unmodifiableMultiset(
     73       Multiset<? extends E> multiset) {
     74     if (multiset instanceof UnmodifiableMultiset ||
     75         multiset instanceof ImmutableMultiset) {
     76       // Since it's unmodifiable, the covariant cast is safe
     77       @SuppressWarnings("unchecked")
     78       Multiset<E> result = (Multiset<E>) multiset;
     79       return result;
     80     }
     81     return new UnmodifiableMultiset<E>(checkNotNull(multiset));
     82   }
     83 
     84   /**
     85    * Simply returns its argument.
     86    *
     87    * @deprecated no need to use this
     88    * @since 10.0
     89    */
     90   @Deprecated public static <E> Multiset<E> unmodifiableMultiset(
     91       ImmutableMultiset<E> multiset) {
     92     return checkNotNull(multiset);
     93   }
     94 
     95   static class UnmodifiableMultiset<E>
     96       extends ForwardingMultiset<E> implements Serializable {
     97     final Multiset<? extends E> delegate;
     98 
     99     UnmodifiableMultiset(Multiset<? extends E> delegate) {
    100       this.delegate = delegate;
    101     }
    102 
    103     @SuppressWarnings("unchecked")
    104     @Override protected Multiset<E> delegate() {
    105       // This is safe because all non-covariant methods are overriden
    106       return (Multiset<E>) delegate;
    107     }
    108 
    109     transient Set<E> elementSet;
    110 
    111     Set<E> createElementSet() {
    112       return Collections.<E>unmodifiableSet(delegate.elementSet());
    113     }
    114 
    115     @Override
    116     public Set<E> elementSet() {
    117       Set<E> es = elementSet;
    118       return (es == null) ? elementSet = createElementSet() : es;
    119     }
    120 
    121     transient Set<Multiset.Entry<E>> entrySet;
    122 
    123     @SuppressWarnings("unchecked")
    124     @Override public Set<Multiset.Entry<E>> entrySet() {
    125       Set<Multiset.Entry<E>> es = entrySet;
    126       return (es == null)
    127           // Safe because the returned set is made unmodifiable and Entry
    128           // itself is readonly
    129           ? entrySet = (Set) Collections.unmodifiableSet(delegate.entrySet())
    130           : es;
    131     }
    132 
    133     @SuppressWarnings("unchecked")
    134     @Override public Iterator<E> iterator() {
    135       // Safe because the returned Iterator is made unmodifiable
    136       return (Iterator<E>) Iterators.unmodifiableIterator(delegate.iterator());
    137     }
    138 
    139     @Override public boolean add(E element) {
    140       throw new UnsupportedOperationException();
    141     }
    142 
    143     @Override public int add(E element, int occurences) {
    144       throw new UnsupportedOperationException();
    145     }
    146 
    147     @Override public boolean addAll(Collection<? extends E> elementsToAdd) {
    148       throw new UnsupportedOperationException();
    149     }
    150 
    151     @Override public boolean remove(Object element) {
    152       throw new UnsupportedOperationException();
    153     }
    154 
    155     @Override public int remove(Object element, int occurrences) {
    156       throw new UnsupportedOperationException();
    157     }
    158 
    159     @Override public boolean removeAll(Collection<?> elementsToRemove) {
    160       throw new UnsupportedOperationException();
    161     }
    162 
    163     @Override public boolean retainAll(Collection<?> elementsToRetain) {
    164       throw new UnsupportedOperationException();
    165     }
    166 
    167     @Override public void clear() {
    168       throw new UnsupportedOperationException();
    169     }
    170 
    171     @Override public int setCount(E element, int count) {
    172       throw new UnsupportedOperationException();
    173     }
    174 
    175     @Override public boolean setCount(E element, int oldCount, int newCount) {
    176       throw new UnsupportedOperationException();
    177     }
    178 
    179     private static final long serialVersionUID = 0;
    180   }
    181 
    182   /**
    183    * Returns an unmodifiable view of the specified sorted multiset. Query
    184    * operations on the returned multiset "read through" to the specified
    185    * multiset, and attempts to modify the returned multiset result in an {@link
    186    * UnsupportedOperationException}.
    187    *
    188    * <p>The returned multiset will be serializable if the specified multiset is
    189    * serializable.
    190    *
    191    * @param sortedMultiset the sorted multiset for which an unmodifiable view is
    192    *     to be generated
    193    * @return an unmodifiable view of the multiset
    194    * @since 11.0
    195    */
    196   @Beta
    197   public static <E> SortedMultiset<E> unmodifiableSortedMultiset(
    198       SortedMultiset<E> sortedMultiset) {
    199     // it's in its own file so it can be emulated for GWT
    200     return new UnmodifiableSortedMultiset<E>(checkNotNull(sortedMultiset));
    201   }
    202 
    203   /**
    204    * Returns an immutable multiset entry with the specified element and count.
    205    * The entry will be serializable if {@code e} is.
    206    *
    207    * @param e the element to be associated with the returned entry
    208    * @param n the count to be associated with the returned entry
    209    * @throws IllegalArgumentException if {@code n} is negative
    210    */
    211   public static <E> Multiset.Entry<E> immutableEntry(@Nullable E e, int n) {
    212     return new ImmutableEntry<E>(e, n);
    213   }
    214 
    215   static final class ImmutableEntry<E> extends AbstractEntry<E> implements
    216       Serializable {
    217     @Nullable final E element;
    218     final int count;
    219 
    220     ImmutableEntry(@Nullable E element, int count) {
    221       this.element = element;
    222       this.count = count;
    223       checkNonnegative(count, "count");
    224     }
    225 
    226     @Override
    227     @Nullable public E getElement() {
    228       return element;
    229     }
    230 
    231     @Override
    232     public int getCount() {
    233       return count;
    234     }
    235 
    236     private static final long serialVersionUID = 0;
    237   }
    238 
    239   /**
    240    * Returns a view of the elements of {@code unfiltered} that satisfy a predicate. The returned
    241    * multiset is a live view of {@code unfiltered}; changes to one affect the other.
    242    *
    243    * <p>The resulting multiset's iterators, and those of its {@code entrySet()} and
    244    * {@code elementSet()}, do not support {@code remove()}.  However, all other multiset methods
    245    * supported by {@code unfiltered} are supported by the returned multiset. When given an element
    246    * that doesn't satisfy the predicate, the multiset's {@code add()} and {@code addAll()} methods
    247    * throw an {@link IllegalArgumentException}. When methods such as {@code removeAll()} and
    248    * {@code clear()} are called on the filtered multiset, only elements that satisfy the filter
    249    * will be removed from the underlying multiset.
    250    *
    251    * <p>The returned multiset isn't threadsafe or serializable, even if {@code unfiltered} is.
    252    *
    253    * <p>Many of the filtered multiset's methods, such as {@code size()}, iterate across every
    254    * element in the underlying multiset and determine which elements satisfy the filter. When a
    255    * live view is <i>not</i> needed, it may be faster to copy the returned multiset and use the
    256    * copy.
    257    *
    258    * <p><b>Warning:</b> {@code predicate} must be <i>consistent with equals</i>, as documented at
    259    * {@link Predicate#apply}. Do not provide a predicate such as
    260    * {@code Predicates.instanceOf(ArrayList.class)}, which is inconsistent with equals. (See
    261    * {@link Iterables#filter(Iterable, Class)} for related functionality.)
    262    *
    263    * @since 14.0
    264    */
    265   @Beta
    266   public static <E> Multiset<E> filter(Multiset<E> unfiltered, Predicate<? super E> predicate) {
    267     if (unfiltered instanceof FilteredMultiset) {
    268       // Support clear(), removeAll(), and retainAll() when filtering a filtered
    269       // collection.
    270       FilteredMultiset<E> filtered = (FilteredMultiset<E>) unfiltered;
    271       Predicate<E> combinedPredicate
    272           = Predicates.<E>and(filtered.predicate, predicate);
    273       return new FilteredMultiset<E>(filtered.unfiltered, combinedPredicate);
    274     }
    275     return new FilteredMultiset<E>(unfiltered, predicate);
    276   }
    277 
    278   private static final class FilteredMultiset<E> extends AbstractMultiset<E> {
    279     final Multiset<E> unfiltered;
    280     final Predicate<? super E> predicate;
    281 
    282     FilteredMultiset(Multiset<E> unfiltered, Predicate<? super E> predicate) {
    283       this.unfiltered = checkNotNull(unfiltered);
    284       this.predicate = checkNotNull(predicate);
    285     }
    286 
    287     @Override
    288     public UnmodifiableIterator<E> iterator() {
    289       return Iterators.filter(unfiltered.iterator(), predicate);
    290     }
    291 
    292     @Override
    293     Set<E> createElementSet() {
    294       return Sets.filter(unfiltered.elementSet(), predicate);
    295     }
    296 
    297     @Override
    298     Set<Entry<E>> createEntrySet() {
    299       return Sets.filter(unfiltered.entrySet(), new Predicate<Entry<E>>() {
    300         @Override
    301         public boolean apply(Entry<E> entry) {
    302           return predicate.apply(entry.getElement());
    303         }
    304       });
    305     }
    306 
    307     @Override
    308     Iterator<Entry<E>> entryIterator() {
    309       throw new AssertionError("should never be called");
    310     }
    311 
    312     @Override
    313     int distinctElements() {
    314       return elementSet().size();
    315     }
    316 
    317     @Override
    318     public int count(@Nullable Object element) {
    319       int count = unfiltered.count(element);
    320       if (count > 0) {
    321         @SuppressWarnings("unchecked") // element is equal to an E
    322         E e = (E) element;
    323         return predicate.apply(e) ? count : 0;
    324       }
    325       return 0;
    326     }
    327 
    328     @Override
    329     public int add(@Nullable E element, int occurrences) {
    330       checkArgument(predicate.apply(element),
    331           "Element %s does not match predicate %s", element, predicate);
    332       return unfiltered.add(element, occurrences);
    333     }
    334 
    335     @Override
    336     public int remove(@Nullable Object element, int occurrences) {
    337       checkNonnegative(occurrences, "occurrences");
    338       if (occurrences == 0) {
    339         return count(element);
    340       } else {
    341         return contains(element) ? unfiltered.remove(element, occurrences) : 0;
    342       }
    343     }
    344 
    345     @Override
    346     public void clear() {
    347       elementSet().clear();
    348     }
    349   }
    350 
    351   /**
    352    * Returns the expected number of distinct elements given the specified
    353    * elements. The number of distinct elements is only computed if {@code
    354    * elements} is an instance of {@code Multiset}; otherwise the default value
    355    * of 11 is returned.
    356    */
    357   static int inferDistinctElements(Iterable<?> elements) {
    358     if (elements instanceof Multiset) {
    359       return ((Multiset<?>) elements).elementSet().size();
    360     }
    361     return 11; // initial capacity will be rounded up to 16
    362   }
    363 
    364   /**
    365    * Returns an unmodifiable view of the union of two multisets.
    366    * In the returned multiset, the count of each element is the <i>maximum</i>
    367    * of its counts in the two backing multisets. The iteration order of the
    368    * returned multiset matches that of the element set of {@code multiset1}
    369    * followed by the members of the element set of {@code multiset2} that are
    370    * not contained in {@code multiset1}, with repeated occurrences of the same
    371    * element appearing consecutively.
    372    *
    373    * <p>Results are undefined if {@code multiset1} and {@code multiset2} are
    374    * based on different equivalence relations (as {@code HashMultiset} and
    375    * {@code TreeMultiset} are).
    376    *
    377    * @since 14.0
    378    */
    379   @Beta
    380   public static <E> Multiset<E> union(
    381       final Multiset<? extends E> multiset1, final Multiset<? extends E> multiset2) {
    382     checkNotNull(multiset1);
    383     checkNotNull(multiset2);
    384 
    385     return new AbstractMultiset<E>() {
    386       @Override
    387       public boolean contains(@Nullable Object element) {
    388         return multiset1.contains(element) || multiset2.contains(element);
    389       }
    390 
    391       @Override
    392       public boolean isEmpty() {
    393         return multiset1.isEmpty() && multiset2.isEmpty();
    394       }
    395 
    396       @Override
    397       public int count(Object element) {
    398         return Math.max(multiset1.count(element), multiset2.count(element));
    399       }
    400 
    401       @Override
    402       Set<E> createElementSet() {
    403         return Sets.union(multiset1.elementSet(), multiset2.elementSet());
    404       }
    405 
    406       @Override
    407       Iterator<Entry<E>> entryIterator() {
    408         final Iterator<? extends Entry<? extends E>> iterator1
    409             = multiset1.entrySet().iterator();
    410         final Iterator<? extends Entry<? extends E>> iterator2
    411             = multiset2.entrySet().iterator();
    412         // TODO(user): consider making the entries live views
    413         return new AbstractIterator<Entry<E>>() {
    414           @Override
    415           protected Entry<E> computeNext() {
    416             if (iterator1.hasNext()) {
    417               Entry<? extends E> entry1 = iterator1.next();
    418               E element = entry1.getElement();
    419               int count = Math.max(entry1.getCount(), multiset2.count(element));
    420               return immutableEntry(element, count);
    421             }
    422             while (iterator2.hasNext()) {
    423               Entry<? extends E> entry2 = iterator2.next();
    424               E element = entry2.getElement();
    425               if (!multiset1.contains(element)) {
    426                 return immutableEntry(element, entry2.getCount());
    427               }
    428             }
    429             return endOfData();
    430           }
    431         };
    432       }
    433 
    434       @Override
    435       int distinctElements() {
    436         return elementSet().size();
    437       }
    438     };
    439   }
    440 
    441   /**
    442    * Returns an unmodifiable view of the intersection of two multisets.
    443    * In the returned multiset, the count of each element is the <i>minimum</i>
    444    * of its counts in the two backing multisets, with elements that would have
    445    * a count of 0 not included. The iteration order of the returned multiset
    446    * matches that of the element set of {@code multiset1}, with repeated
    447    * occurrences of the same element appearing consecutively.
    448    *
    449    * <p>Results are undefined if {@code multiset1} and {@code multiset2} are
    450    * based on different equivalence relations (as {@code HashMultiset} and
    451    * {@code TreeMultiset} are).
    452    *
    453    * @since 2.0
    454    */
    455   public static <E> Multiset<E> intersection(
    456       final Multiset<E> multiset1, final Multiset<?> multiset2) {
    457     checkNotNull(multiset1);
    458     checkNotNull(multiset2);
    459 
    460     return new AbstractMultiset<E>() {
    461       @Override
    462       public int count(Object element) {
    463         int count1 = multiset1.count(element);
    464         return (count1 == 0) ? 0 : Math.min(count1, multiset2.count(element));
    465       }
    466 
    467       @Override
    468       Set<E> createElementSet() {
    469         return Sets.intersection(
    470             multiset1.elementSet(), multiset2.elementSet());
    471       }
    472 
    473       @Override
    474       Iterator<Entry<E>> entryIterator() {
    475         final Iterator<Entry<E>> iterator1 = multiset1.entrySet().iterator();
    476         // TODO(user): consider making the entries live views
    477         return new AbstractIterator<Entry<E>>() {
    478           @Override
    479           protected Entry<E> computeNext() {
    480             while (iterator1.hasNext()) {
    481               Entry<E> entry1 = iterator1.next();
    482               E element = entry1.getElement();
    483               int count = Math.min(entry1.getCount(), multiset2.count(element));
    484               if (count > 0) {
    485                 return immutableEntry(element, count);
    486               }
    487             }
    488             return endOfData();
    489           }
    490         };
    491       }
    492 
    493       @Override
    494       int distinctElements() {
    495         return elementSet().size();
    496       }
    497     };
    498   }
    499 
    500   /**
    501    * Returns an unmodifiable view of the sum of two multisets.
    502    * In the returned multiset, the count of each element is the <i>sum</i> of
    503    * its counts in the two backing multisets. The iteration order of the
    504    * returned multiset matches that of the element set of {@code multiset1}
    505    * followed by the members of the element set of {@code multiset2} that
    506    * are not contained in {@code multiset1}, with repeated occurrences of the
    507    * same element appearing consecutively.
    508    *
    509    * <p>Results are undefined if {@code multiset1} and {@code multiset2} are
    510    * based on different equivalence relations (as {@code HashMultiset} and
    511    * {@code TreeMultiset} are).
    512    *
    513    * @since 14.0
    514    */
    515   @Beta
    516   public static <E> Multiset<E> sum(
    517       final Multiset<? extends E> multiset1, final Multiset<? extends E> multiset2) {
    518     checkNotNull(multiset1);
    519     checkNotNull(multiset2);
    520 
    521     // TODO(user): consider making the entries live views
    522     return new AbstractMultiset<E>() {
    523       @Override
    524       public boolean contains(@Nullable Object element) {
    525         return multiset1.contains(element) || multiset2.contains(element);
    526       }
    527 
    528       @Override
    529       public boolean isEmpty() {
    530         return multiset1.isEmpty() && multiset2.isEmpty();
    531       }
    532 
    533       @Override
    534       public int size() {
    535         return multiset1.size() + multiset2.size();
    536       }
    537 
    538       @Override
    539       public int count(Object element) {
    540         return multiset1.count(element) + multiset2.count(element);
    541       }
    542 
    543       @Override
    544       Set<E> createElementSet() {
    545         return Sets.union(multiset1.elementSet(), multiset2.elementSet());
    546       }
    547 
    548       @Override
    549       Iterator<Entry<E>> entryIterator() {
    550         final Iterator<? extends Entry<? extends E>> iterator1
    551             = multiset1.entrySet().iterator();
    552         final Iterator<? extends Entry<? extends E>> iterator2
    553             = multiset2.entrySet().iterator();
    554         return new AbstractIterator<Entry<E>>() {
    555           @Override
    556           protected Entry<E> computeNext() {
    557             if (iterator1.hasNext()) {
    558               Entry<? extends E> entry1 = iterator1.next();
    559               E element = entry1.getElement();
    560               int count = entry1.getCount() + multiset2.count(element);
    561               return immutableEntry(element, count);
    562             }
    563             while (iterator2.hasNext()) {
    564               Entry<? extends E> entry2 = iterator2.next();
    565               E element = entry2.getElement();
    566               if (!multiset1.contains(element)) {
    567                 return immutableEntry(element, entry2.getCount());
    568               }
    569             }
    570             return endOfData();
    571           }
    572         };
    573       }
    574 
    575       @Override
    576       int distinctElements() {
    577         return elementSet().size();
    578       }
    579     };
    580   }
    581 
    582   /**
    583    * Returns an unmodifiable view of the difference of two multisets.
    584    * In the returned multiset, the count of each element is the result of the
    585    * <i>zero-truncated subtraction</i> of its count in the second multiset from
    586    * its count in the first multiset, with elements that would have a count of
    587    * 0 not included. The iteration order of the returned multiset matches that
    588    * of the element set of {@code multiset1}, with repeated occurrences of the
    589    * same element appearing consecutively.
    590    *
    591    * <p>Results are undefined if {@code multiset1} and {@code multiset2} are
    592    * based on different equivalence relations (as {@code HashMultiset} and
    593    * {@code TreeMultiset} are).
    594    *
    595    * @since 14.0
    596    */
    597   @Beta
    598   public static <E> Multiset<E> difference(
    599       final Multiset<E> multiset1, final Multiset<?> multiset2) {
    600     checkNotNull(multiset1);
    601     checkNotNull(multiset2);
    602 
    603     // TODO(user): consider making the entries live views
    604     return new AbstractMultiset<E>() {
    605       @Override
    606       public int count(@Nullable Object element) {
    607         int count1 = multiset1.count(element);
    608         return (count1 == 0) ? 0 :
    609             Math.max(0, count1 - multiset2.count(element));
    610       }
    611 
    612       @Override
    613       Iterator<Entry<E>> entryIterator() {
    614         final Iterator<Entry<E>> iterator1 = multiset1.entrySet().iterator();
    615         return new AbstractIterator<Entry<E>>() {
    616           @Override
    617           protected Entry<E> computeNext() {
    618             while (iterator1.hasNext()) {
    619               Entry<E> entry1 = iterator1.next();
    620               E element = entry1.getElement();
    621               int count = entry1.getCount() - multiset2.count(element);
    622               if (count > 0) {
    623                 return immutableEntry(element, count);
    624               }
    625             }
    626             return endOfData();
    627           }
    628         };
    629       }
    630 
    631       @Override
    632       int distinctElements() {
    633         return Iterators.size(entryIterator());
    634       }
    635     };
    636   }
    637 
    638   /**
    639    * Returns {@code true} if {@code subMultiset.count(o) <=
    640    * superMultiset.count(o)} for all {@code o}.
    641    *
    642    * @since 10.0
    643    */
    644   public static boolean containsOccurrences(
    645       Multiset<?> superMultiset, Multiset<?> subMultiset) {
    646     checkNotNull(superMultiset);
    647     checkNotNull(subMultiset);
    648     for (Entry<?> entry : subMultiset.entrySet()) {
    649       int superCount = superMultiset.count(entry.getElement());
    650       if (superCount < entry.getCount()) {
    651         return false;
    652       }
    653     }
    654     return true;
    655   }
    656 
    657   /**
    658    * Modifies {@code multisetToModify} so that its count for an element
    659    * {@code e} is at most {@code multisetToRetain.count(e)}.
    660    *
    661    * <p>To be precise, {@code multisetToModify.count(e)} is set to
    662    * {@code Math.min(multisetToModify.count(e),
    663    * multisetToRetain.count(e))}. This is similar to
    664    * {@link #intersection(Multiset, Multiset) intersection}
    665    * {@code (multisetToModify, multisetToRetain)}, but mutates
    666    * {@code multisetToModify} instead of returning a view.
    667    *
    668    * <p>In contrast, {@code multisetToModify.retainAll(multisetToRetain)} keeps
    669    * all occurrences of elements that appear at all in {@code
    670    * multisetToRetain}, and deletes all occurrences of all other elements.
    671    *
    672    * @return {@code true} if {@code multisetToModify} was changed as a result
    673    *         of this operation
    674    * @since 10.0
    675    */
    676   public static boolean retainOccurrences(Multiset<?> multisetToModify,
    677       Multiset<?> multisetToRetain) {
    678     return retainOccurrencesImpl(multisetToModify, multisetToRetain);
    679   }
    680 
    681   /**
    682    * Delegate implementation which cares about the element type.
    683    */
    684   private static <E> boolean retainOccurrencesImpl(
    685       Multiset<E> multisetToModify, Multiset<?> occurrencesToRetain) {
    686     checkNotNull(multisetToModify);
    687     checkNotNull(occurrencesToRetain);
    688     // Avoiding ConcurrentModificationExceptions is tricky.
    689     Iterator<Entry<E>> entryIterator = multisetToModify.entrySet().iterator();
    690     boolean changed = false;
    691     while (entryIterator.hasNext()) {
    692       Entry<E> entry = entryIterator.next();
    693       int retainCount = occurrencesToRetain.count(entry.getElement());
    694       if (retainCount == 0) {
    695         entryIterator.remove();
    696         changed = true;
    697       } else if (retainCount < entry.getCount()) {
    698         multisetToModify.setCount(entry.getElement(), retainCount);
    699         changed = true;
    700       }
    701     }
    702     return changed;
    703   }
    704 
    705   /**
    706    * For each occurrence of an element {@code e} in {@code occurrencesToRemove},
    707    * removes one occurrence of {@code e} in {@code multisetToModify}.
    708    *
    709    * <p>Equivalently, this method modifies {@code multisetToModify} so that
    710    * {@code multisetToModify.count(e)} is set to
    711    * {@code Math.max(0, multisetToModify.count(e) -
    712    * occurrencesToRemove.count(e))}.
    713    *
    714    * <p>This is <i>not</i> the same as {@code multisetToModify.}
    715    * {@link Multiset#removeAll removeAll}{@code (occurrencesToRemove)}, which
    716    * removes all occurrences of elements that appear in
    717    * {@code occurrencesToRemove}. However, this operation <i>is</i> equivalent
    718    * to, albeit sometimes more efficient than, the following: <pre>   {@code
    719    *
    720    *   for (E e : occurrencesToRemove) {
    721    *     multisetToModify.remove(e);
    722    *   }}</pre>
    723    *
    724    * @return {@code true} if {@code multisetToModify} was changed as a result of
    725    *         this operation
    726    * @since 18.0 (present in 10.0 with a requirement that the second parameter
    727    *     be a {@code Multiset})
    728    */
    729   public static boolean removeOccurrences(
    730       Multiset<?> multisetToModify, Iterable<?> occurrencesToRemove) {
    731     if (occurrencesToRemove instanceof Multiset) {
    732       return removeOccurrencesImpl(
    733           multisetToModify, (Multiset<?>) occurrencesToRemove);
    734     } else {
    735       return removeOccurrencesImpl(multisetToModify, occurrencesToRemove);
    736     }
    737   }
    738 
    739   private static boolean removeOccurrencesImpl(
    740       Multiset<?> multisetToModify, Iterable<?> occurrencesToRemove) {
    741     checkNotNull(multisetToModify);
    742     checkNotNull(occurrencesToRemove);
    743     boolean changed = false;
    744     for (Object o : occurrencesToRemove) {
    745       changed |= multisetToModify.remove(o);
    746     }
    747     return changed;
    748   }
    749 
    750   /**
    751    * Delegate that cares about the element types in multisetToModify.
    752    */
    753   private static <E> boolean removeOccurrencesImpl(
    754       Multiset<E> multisetToModify, Multiset<?> occurrencesToRemove) {
    755     // TODO(user): generalize to removing an Iterable, perhaps
    756     checkNotNull(multisetToModify);
    757     checkNotNull(occurrencesToRemove);
    758 
    759     boolean changed = false;
    760     Iterator<Entry<E>> entryIterator = multisetToModify.entrySet().iterator();
    761     while (entryIterator.hasNext()) {
    762       Entry<E> entry = entryIterator.next();
    763       int removeCount = occurrencesToRemove.count(entry.getElement());
    764       if (removeCount >= entry.getCount()) {
    765         entryIterator.remove();
    766         changed = true;
    767       } else if (removeCount > 0) {
    768         multisetToModify.remove(entry.getElement(), removeCount);
    769         changed = true;
    770       }
    771     }
    772     return changed;
    773   }
    774 
    775   /**
    776    * Implementation of the {@code equals}, {@code hashCode}, and
    777    * {@code toString} methods of {@link Multiset.Entry}.
    778    */
    779   abstract static class AbstractEntry<E> implements Multiset.Entry<E> {
    780     /**
    781      * Indicates whether an object equals this entry, following the behavior
    782      * specified in {@link Multiset.Entry#equals}.
    783      */
    784     @Override public boolean equals(@Nullable Object object) {
    785       if (object instanceof Multiset.Entry) {
    786         Multiset.Entry<?> that = (Multiset.Entry<?>) object;
    787         return this.getCount() == that.getCount()
    788             && Objects.equal(this.getElement(), that.getElement());
    789       }
    790       return false;
    791     }
    792 
    793     /**
    794      * Return this entry's hash code, following the behavior specified in
    795      * {@link Multiset.Entry#hashCode}.
    796      */
    797     @Override public int hashCode() {
    798       E e = getElement();
    799       return ((e == null) ? 0 : e.hashCode()) ^ getCount();
    800     }
    801 
    802     /**
    803      * Returns a string representation of this multiset entry. The string
    804      * representation consists of the associated element if the associated count
    805      * is one, and otherwise the associated element followed by the characters
    806      * " x " (space, x and space) followed by the count. Elements and counts are
    807      * converted to strings as by {@code String.valueOf}.
    808      */
    809     @Override public String toString() {
    810       String text = String.valueOf(getElement());
    811       int n = getCount();
    812       return (n == 1) ? text : (text + " x " + n);
    813     }
    814   }
    815 
    816   /**
    817    * An implementation of {@link Multiset#equals}.
    818    */
    819   static boolean equalsImpl(Multiset<?> multiset, @Nullable Object object) {
    820     if (object == multiset) {
    821       return true;
    822     }
    823     if (object instanceof Multiset) {
    824       Multiset<?> that = (Multiset<?>) object;
    825       /*
    826        * We can't simply check whether the entry sets are equal, since that
    827        * approach fails when a TreeMultiset has a comparator that returns 0
    828        * when passed unequal elements.
    829        */
    830 
    831       if (multiset.size() != that.size()
    832           || multiset.entrySet().size() != that.entrySet().size()) {
    833         return false;
    834       }
    835       for (Entry<?> entry : that.entrySet()) {
    836         if (multiset.count(entry.getElement()) != entry.getCount()) {
    837           return false;
    838         }
    839       }
    840       return true;
    841     }
    842     return false;
    843   }
    844 
    845   /**
    846    * An implementation of {@link Multiset#addAll}.
    847    */
    848   static <E> boolean addAllImpl(
    849       Multiset<E> self, Collection<? extends E> elements) {
    850     if (elements.isEmpty()) {
    851       return false;
    852     }
    853     if (elements instanceof Multiset) {
    854       Multiset<? extends E> that = cast(elements);
    855       for (Entry<? extends E> entry : that.entrySet()) {
    856         self.add(entry.getElement(), entry.getCount());
    857       }
    858     } else {
    859       Iterators.addAll(self, elements.iterator());
    860     }
    861     return true;
    862   }
    863 
    864   /**
    865    * An implementation of {@link Multiset#removeAll}.
    866    */
    867   static boolean removeAllImpl(
    868       Multiset<?> self, Collection<?> elementsToRemove) {
    869     Collection<?> collection = (elementsToRemove instanceof Multiset)
    870         ? ((Multiset<?>) elementsToRemove).elementSet() : elementsToRemove;
    871 
    872     return self.elementSet().removeAll(collection);
    873   }
    874 
    875   /**
    876    * An implementation of {@link Multiset#retainAll}.
    877    */
    878   static boolean retainAllImpl(
    879       Multiset<?> self, Collection<?> elementsToRetain) {
    880     checkNotNull(elementsToRetain);
    881     Collection<?> collection = (elementsToRetain instanceof Multiset)
    882         ? ((Multiset<?>) elementsToRetain).elementSet() : elementsToRetain;
    883 
    884     return self.elementSet().retainAll(collection);
    885   }
    886 
    887   /**
    888    * An implementation of {@link Multiset#setCount(Object, int)}.
    889    */
    890   static <E> int setCountImpl(Multiset<E> self, E element, int count) {
    891     checkNonnegative(count, "count");
    892 
    893     int oldCount = self.count(element);
    894 
    895     int delta = count - oldCount;
    896     if (delta > 0) {
    897       self.add(element, delta);
    898     } else if (delta < 0) {
    899       self.remove(element, -delta);
    900     }
    901 
    902     return oldCount;
    903   }
    904 
    905   /**
    906    * An implementation of {@link Multiset#setCount(Object, int, int)}.
    907    */
    908   static <E> boolean setCountImpl(
    909       Multiset<E> self, E element, int oldCount, int newCount) {
    910     checkNonnegative(oldCount, "oldCount");
    911     checkNonnegative(newCount, "newCount");
    912 
    913     if (self.count(element) == oldCount) {
    914       self.setCount(element, newCount);
    915       return true;
    916     } else {
    917       return false;
    918     }
    919   }
    920 
    921   abstract static class ElementSet<E> extends Sets.ImprovedAbstractSet<E> {
    922     abstract Multiset<E> multiset();
    923 
    924     @Override public void clear() {
    925       multiset().clear();
    926     }
    927 
    928     @Override public boolean contains(Object o) {
    929       return multiset().contains(o);
    930     }
    931 
    932     @Override public boolean containsAll(Collection<?> c) {
    933       return multiset().containsAll(c);
    934     }
    935 
    936     @Override public boolean isEmpty() {
    937       return multiset().isEmpty();
    938     }
    939 
    940     @Override public Iterator<E> iterator() {
    941       return new TransformedIterator<Entry<E>, E>(multiset().entrySet().iterator()) {
    942         @Override
    943         E transform(Entry<E> entry) {
    944           return entry.getElement();
    945         }
    946       };
    947     }
    948 
    949     @Override
    950     public boolean remove(Object o) {
    951       int count = multiset().count(o);
    952       if (count > 0) {
    953         multiset().remove(o, count);
    954         return true;
    955       }
    956       return false;
    957     }
    958 
    959     @Override public int size() {
    960       return multiset().entrySet().size();
    961     }
    962   }
    963 
    964   abstract static class EntrySet<E> extends Sets.ImprovedAbstractSet<Entry<E>> {
    965     abstract Multiset<E> multiset();
    966 
    967     @Override public boolean contains(@Nullable Object o) {
    968       if (o instanceof Entry) {
    969         /*
    970          * The GWT compiler wrongly issues a warning here.
    971          */
    972         @SuppressWarnings("cast")
    973         Entry<?> entry = (Entry<?>) o;
    974         if (entry.getCount() <= 0) {
    975           return false;
    976         }
    977         int count = multiset().count(entry.getElement());
    978         return count == entry.getCount();
    979 
    980       }
    981       return false;
    982     }
    983 
    984     // GWT compiler warning; see contains().
    985     @SuppressWarnings("cast")
    986     @Override public boolean remove(Object object) {
    987       if (object instanceof Multiset.Entry) {
    988         Entry<?> entry = (Entry<?>) object;
    989         Object element = entry.getElement();
    990         int entryCount = entry.getCount();
    991         if (entryCount != 0) {
    992           // Safe as long as we never add a new entry, which we won't.
    993           @SuppressWarnings("unchecked")
    994           Multiset<Object> multiset = (Multiset) multiset();
    995           return multiset.setCount(element, entryCount, 0);
    996         }
    997       }
    998       return false;
    999     }
   1000 
   1001     @Override public void clear() {
   1002       multiset().clear();
   1003     }
   1004   }
   1005 
   1006   /**
   1007    * An implementation of {@link Multiset#iterator}.
   1008    */
   1009   static <E> Iterator<E> iteratorImpl(Multiset<E> multiset) {
   1010     return new MultisetIteratorImpl<E>(
   1011         multiset, multiset.entrySet().iterator());
   1012   }
   1013 
   1014   static final class MultisetIteratorImpl<E> implements Iterator<E> {
   1015     private final Multiset<E> multiset;
   1016     private final Iterator<Entry<E>> entryIterator;
   1017     private Entry<E> currentEntry;
   1018     /** Count of subsequent elements equal to current element */
   1019     private int laterCount;
   1020     /** Count of all elements equal to current element */
   1021     private int totalCount;
   1022     private boolean canRemove;
   1023 
   1024     MultisetIteratorImpl(
   1025         Multiset<E> multiset, Iterator<Entry<E>> entryIterator) {
   1026       this.multiset = multiset;
   1027       this.entryIterator = entryIterator;
   1028     }
   1029 
   1030     @Override
   1031     public boolean hasNext() {
   1032       return laterCount > 0 || entryIterator.hasNext();
   1033     }
   1034 
   1035     @Override
   1036     public E next() {
   1037       if (!hasNext()) {
   1038         throw new NoSuchElementException();
   1039       }
   1040       if (laterCount == 0) {
   1041         currentEntry = entryIterator.next();
   1042         totalCount = laterCount = currentEntry.getCount();
   1043       }
   1044       laterCount--;
   1045       canRemove = true;
   1046       return currentEntry.getElement();
   1047     }
   1048 
   1049     @Override
   1050     public void remove() {
   1051       checkRemove(canRemove);
   1052       if (totalCount == 1) {
   1053         entryIterator.remove();
   1054       } else {
   1055         multiset.remove(currentEntry.getElement());
   1056       }
   1057       totalCount--;
   1058       canRemove = false;
   1059     }
   1060   }
   1061 
   1062   /**
   1063    * An implementation of {@link Multiset#size}.
   1064    */
   1065   static int sizeImpl(Multiset<?> multiset) {
   1066     long size = 0;
   1067     for (Entry<?> entry : multiset.entrySet()) {
   1068       size += entry.getCount();
   1069     }
   1070     return Ints.saturatedCast(size);
   1071   }
   1072 
   1073   /**
   1074    * Used to avoid http://bugs.sun.com/view_bug.do?bug_id=6558557
   1075    */
   1076   static <T> Multiset<T> cast(Iterable<T> iterable) {
   1077     return (Multiset<T>) iterable;
   1078   }
   1079 
   1080   private static final Ordering<Entry<?>> DECREASING_COUNT_ORDERING = new Ordering<Entry<?>>() {
   1081     @Override
   1082     public int compare(Entry<?> entry1, Entry<?> entry2) {
   1083       return Ints.compare(entry2.getCount(), entry1.getCount());
   1084     }
   1085   };
   1086 
   1087   /**
   1088    * Returns a copy of {@code multiset} as an {@link ImmutableMultiset} whose iteration order is
   1089    * highest count first, with ties broken by the iteration order of the original multiset.
   1090    *
   1091    * @since 11.0
   1092    */
   1093   @Beta
   1094   public static <E> ImmutableMultiset<E> copyHighestCountFirst(Multiset<E> multiset) {
   1095     List<Entry<E>> sortedEntries =
   1096         Multisets.DECREASING_COUNT_ORDERING.immutableSortedCopy(multiset.entrySet());
   1097     return ImmutableMultiset.copyFromEntries(sortedEntries);
   1098   }
   1099 }
   1100