• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
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    */
unmodifiableMultiset( Multiset<? extends E> multiset)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    */
unmodifiableMultiset( ImmutableMultiset<E> multiset)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 
UnmodifiableMultiset(Multiset<? extends E> delegate)99     UnmodifiableMultiset(Multiset<? extends E> delegate) {
100       this.delegate = delegate;
101     }
102 
103     @SuppressWarnings("unchecked")
delegate()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 
createElementSet()111     Set<E> createElementSet() {
112       return Collections.<E>unmodifiableSet(delegate.elementSet());
113     }
114 
115     @Override
elementSet()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")
entrySet()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")
iterator()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 
add(E element)139     @Override public boolean add(E element) {
140       throw new UnsupportedOperationException();
141     }
142 
add(E element, int occurences)143     @Override public int add(E element, int occurences) {
144       throw new UnsupportedOperationException();
145     }
146 
addAll(Collection<? extends E> elementsToAdd)147     @Override public boolean addAll(Collection<? extends E> elementsToAdd) {
148       throw new UnsupportedOperationException();
149     }
150 
remove(Object element)151     @Override public boolean remove(Object element) {
152       throw new UnsupportedOperationException();
153     }
154 
remove(Object element, int occurrences)155     @Override public int remove(Object element, int occurrences) {
156       throw new UnsupportedOperationException();
157     }
158 
removeAll(Collection<?> elementsToRemove)159     @Override public boolean removeAll(Collection<?> elementsToRemove) {
160       throw new UnsupportedOperationException();
161     }
162 
retainAll(Collection<?> elementsToRetain)163     @Override public boolean retainAll(Collection<?> elementsToRetain) {
164       throw new UnsupportedOperationException();
165     }
166 
clear()167     @Override public void clear() {
168       throw new UnsupportedOperationException();
169     }
170 
setCount(E element, int count)171     @Override public int setCount(E element, int count) {
172       throw new UnsupportedOperationException();
173     }
174 
setCount(E element, int oldCount, int newCount)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
unmodifiableSortedMultiset( SortedMultiset<E> sortedMultiset)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    */
immutableEntry(@ullable E e, int n)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 
ImmutableEntry(@ullable E element, int count)220     ImmutableEntry(@Nullable E element, int count) {
221       this.element = element;
222       this.count = count;
223       checkNonnegative(count, "count");
224     }
225 
226     @Override
getElement()227     @Nullable public E getElement() {
228       return element;
229     }
230 
231     @Override
getCount()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
filter(Multiset<E> unfiltered, Predicate<? super E> predicate)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 
FilteredMultiset(Multiset<E> unfiltered, Predicate<? super E> predicate)282     FilteredMultiset(Multiset<E> unfiltered, Predicate<? super E> predicate) {
283       this.unfiltered = checkNotNull(unfiltered);
284       this.predicate = checkNotNull(predicate);
285     }
286 
287     @Override
iterator()288     public UnmodifiableIterator<E> iterator() {
289       return Iterators.filter(unfiltered.iterator(), predicate);
290     }
291 
292     @Override
createElementSet()293     Set<E> createElementSet() {
294       return Sets.filter(unfiltered.elementSet(), predicate);
295     }
296 
297     @Override
createEntrySet()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
entryIterator()308     Iterator<Entry<E>> entryIterator() {
309       throw new AssertionError("should never be called");
310     }
311 
312     @Override
distinctElements()313     int distinctElements() {
314       return elementSet().size();
315     }
316 
317     @Override
count(@ullable Object element)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
add(@ullable E element, int occurrences)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
remove(@ullable Object element, int occurrences)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
clear()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