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