10888a09821a98ac0680fad765217302858e70fa4Paul Duffin/* 20888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Copyright (C) 2007 The Guava Authors 30888a09821a98ac0680fad765217302858e70fa4Paul Duffin * 40888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License"); 50888a09821a98ac0680fad765217302858e70fa4Paul Duffin * you may not use this file except in compliance with the License. 60888a09821a98ac0680fad765217302858e70fa4Paul Duffin * You may obtain a copy of the License at 70888a09821a98ac0680fad765217302858e70fa4Paul Duffin * 80888a09821a98ac0680fad765217302858e70fa4Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0 90888a09821a98ac0680fad765217302858e70fa4Paul Duffin * 100888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Unless required by applicable law or agreed to in writing, software 110888a09821a98ac0680fad765217302858e70fa4Paul Duffin * distributed under the License is distributed on an "AS IS" BASIS, 120888a09821a98ac0680fad765217302858e70fa4Paul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130888a09821a98ac0680fad765217302858e70fa4Paul Duffin * See the License for the specific language governing permissions and 140888a09821a98ac0680fad765217302858e70fa4Paul Duffin * limitations under the License. 150888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 160888a09821a98ac0680fad765217302858e70fa4Paul Duffin 170888a09821a98ac0680fad765217302858e70fa4Paul Duffinpackage com.google.common.collect; 180888a09821a98ac0680fad765217302858e70fa4Paul Duffin 190888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.base.Preconditions.checkArgument; 200888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.base.Preconditions.checkNotNull; 210888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.collect.CollectPreconditions.checkNonnegative; 220888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.collect.CollectPreconditions.checkRemove; 230888a09821a98ac0680fad765217302858e70fa4Paul Duffin 240888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.annotations.GwtCompatible; 250888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.primitives.Ints; 260888a09821a98ac0680fad765217302858e70fa4Paul Duffin 270888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.io.Serializable; 280888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.util.ConcurrentModificationException; 290888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.util.Iterator; 300888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.util.Map; 310888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.util.Set; 320888a09821a98ac0680fad765217302858e70fa4Paul Duffin 330888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport javax.annotation.Nullable; 340888a09821a98ac0680fad765217302858e70fa4Paul Duffin 350888a09821a98ac0680fad765217302858e70fa4Paul Duffin/** 360888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Basic implementation of {@code Multiset<E>} backed by an instance of {@code 370888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Map<E, Count>}. 380888a09821a98ac0680fad765217302858e70fa4Paul Duffin * 390888a09821a98ac0680fad765217302858e70fa4Paul Duffin * <p>For serialization to work, the subclass must specify explicit {@code 400888a09821a98ac0680fad765217302858e70fa4Paul Duffin * readObject} and {@code writeObject} methods. 410888a09821a98ac0680fad765217302858e70fa4Paul Duffin * 420888a09821a98ac0680fad765217302858e70fa4Paul Duffin * @author Kevin Bourrillion 430888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 440888a09821a98ac0680fad765217302858e70fa4Paul Duffin@GwtCompatible(emulated = true) 450888a09821a98ac0680fad765217302858e70fa4Paul Duffinabstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E> 460888a09821a98ac0680fad765217302858e70fa4Paul Duffin implements Serializable { 470888a09821a98ac0680fad765217302858e70fa4Paul Duffin 480888a09821a98ac0680fad765217302858e70fa4Paul Duffin private transient Map<E, Count> backingMap; 490888a09821a98ac0680fad765217302858e70fa4Paul Duffin 500888a09821a98ac0680fad765217302858e70fa4Paul Duffin /* 510888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Cache the size for efficiency. Using a long lets us avoid the need for 520888a09821a98ac0680fad765217302858e70fa4Paul Duffin * overflow checking and ensures that size() will function correctly even if 530888a09821a98ac0680fad765217302858e70fa4Paul Duffin * the multiset had once been larger than Integer.MAX_VALUE. 540888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 550888a09821a98ac0680fad765217302858e70fa4Paul Duffin private transient long size; 560888a09821a98ac0680fad765217302858e70fa4Paul Duffin 570888a09821a98ac0680fad765217302858e70fa4Paul Duffin /** Standard constructor. */ 580888a09821a98ac0680fad765217302858e70fa4Paul Duffin protected AbstractMapBasedMultiset(Map<E, Count> backingMap) { 590888a09821a98ac0680fad765217302858e70fa4Paul Duffin this.backingMap = checkNotNull(backingMap); 600888a09821a98ac0680fad765217302858e70fa4Paul Duffin this.size = super.size(); 610888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 620888a09821a98ac0680fad765217302858e70fa4Paul Duffin 630888a09821a98ac0680fad765217302858e70fa4Paul Duffin /** Used during deserialization only. The backing map must be empty. */ 640888a09821a98ac0680fad765217302858e70fa4Paul Duffin void setBackingMap(Map<E, Count> backingMap) { 650888a09821a98ac0680fad765217302858e70fa4Paul Duffin this.backingMap = backingMap; 660888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 670888a09821a98ac0680fad765217302858e70fa4Paul Duffin 680888a09821a98ac0680fad765217302858e70fa4Paul Duffin // Required Implementations 690888a09821a98ac0680fad765217302858e70fa4Paul Duffin 700888a09821a98ac0680fad765217302858e70fa4Paul Duffin /** 710888a09821a98ac0680fad765217302858e70fa4Paul Duffin * {@inheritDoc} 720888a09821a98ac0680fad765217302858e70fa4Paul Duffin * 730888a09821a98ac0680fad765217302858e70fa4Paul Duffin * <p>Invoking {@link Multiset.Entry#getCount} on an entry in the returned 740888a09821a98ac0680fad765217302858e70fa4Paul Duffin * set always returns the current count of that element in the multiset, as 750888a09821a98ac0680fad765217302858e70fa4Paul Duffin * opposed to the count at the time the entry was retrieved. 760888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 770888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 780888a09821a98ac0680fad765217302858e70fa4Paul Duffin public Set<Multiset.Entry<E>> entrySet() { 790888a09821a98ac0680fad765217302858e70fa4Paul Duffin return super.entrySet(); 800888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 810888a09821a98ac0680fad765217302858e70fa4Paul Duffin 820888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 830888a09821a98ac0680fad765217302858e70fa4Paul Duffin Iterator<Entry<E>> entryIterator() { 840888a09821a98ac0680fad765217302858e70fa4Paul Duffin final Iterator<Map.Entry<E, Count>> backingEntries = 850888a09821a98ac0680fad765217302858e70fa4Paul Duffin backingMap.entrySet().iterator(); 860888a09821a98ac0680fad765217302858e70fa4Paul Duffin return new Iterator<Multiset.Entry<E>>() { 870888a09821a98ac0680fad765217302858e70fa4Paul Duffin Map.Entry<E, Count> toRemove; 880888a09821a98ac0680fad765217302858e70fa4Paul Duffin 890888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 900888a09821a98ac0680fad765217302858e70fa4Paul Duffin public boolean hasNext() { 910888a09821a98ac0680fad765217302858e70fa4Paul Duffin return backingEntries.hasNext(); 920888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 930888a09821a98ac0680fad765217302858e70fa4Paul Duffin 940888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 950888a09821a98ac0680fad765217302858e70fa4Paul Duffin public Multiset.Entry<E> next() { 960888a09821a98ac0680fad765217302858e70fa4Paul Duffin final Map.Entry<E, Count> mapEntry = backingEntries.next(); 970888a09821a98ac0680fad765217302858e70fa4Paul Duffin toRemove = mapEntry; 980888a09821a98ac0680fad765217302858e70fa4Paul Duffin return new Multisets.AbstractEntry<E>() { 990888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 1000888a09821a98ac0680fad765217302858e70fa4Paul Duffin public E getElement() { 1010888a09821a98ac0680fad765217302858e70fa4Paul Duffin return mapEntry.getKey(); 1020888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1030888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 1040888a09821a98ac0680fad765217302858e70fa4Paul Duffin public int getCount() { 1050888a09821a98ac0680fad765217302858e70fa4Paul Duffin Count count = mapEntry.getValue(); 1060888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (count == null || count.get() == 0) { 1070888a09821a98ac0680fad765217302858e70fa4Paul Duffin Count frequency = backingMap.get(getElement()); 1080888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (frequency != null) { 1090888a09821a98ac0680fad765217302858e70fa4Paul Duffin return frequency.get(); 1100888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1110888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1120888a09821a98ac0680fad765217302858e70fa4Paul Duffin return (count == null) ? 0 : count.get(); 1130888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1140888a09821a98ac0680fad765217302858e70fa4Paul Duffin }; 1150888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1160888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1170888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 1180888a09821a98ac0680fad765217302858e70fa4Paul Duffin public void remove() { 1190888a09821a98ac0680fad765217302858e70fa4Paul Duffin checkRemove(toRemove != null); 1200888a09821a98ac0680fad765217302858e70fa4Paul Duffin size -= toRemove.getValue().getAndSet(0); 1210888a09821a98ac0680fad765217302858e70fa4Paul Duffin backingEntries.remove(); 1220888a09821a98ac0680fad765217302858e70fa4Paul Duffin toRemove = null; 1230888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1240888a09821a98ac0680fad765217302858e70fa4Paul Duffin }; 1250888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1260888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1270888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 1280888a09821a98ac0680fad765217302858e70fa4Paul Duffin public void clear() { 1290888a09821a98ac0680fad765217302858e70fa4Paul Duffin for (Count frequency : backingMap.values()) { 1300888a09821a98ac0680fad765217302858e70fa4Paul Duffin frequency.set(0); 1310888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1320888a09821a98ac0680fad765217302858e70fa4Paul Duffin backingMap.clear(); 1330888a09821a98ac0680fad765217302858e70fa4Paul Duffin size = 0L; 1340888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1350888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1360888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 1370888a09821a98ac0680fad765217302858e70fa4Paul Duffin int distinctElements() { 1380888a09821a98ac0680fad765217302858e70fa4Paul Duffin return backingMap.size(); 1390888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1400888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1410888a09821a98ac0680fad765217302858e70fa4Paul Duffin // Optimizations - Query Operations 1420888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1430888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public int size() { 1440888a09821a98ac0680fad765217302858e70fa4Paul Duffin return Ints.saturatedCast(size); 1450888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1460888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1470888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public Iterator<E> iterator() { 1480888a09821a98ac0680fad765217302858e70fa4Paul Duffin return new MapBasedMultisetIterator(); 1490888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1500888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1510888a09821a98ac0680fad765217302858e70fa4Paul Duffin /* 1520888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Not subclassing AbstractMultiset$MultisetIterator because next() needs to 1530888a09821a98ac0680fad765217302858e70fa4Paul Duffin * retrieve the Map.Entry<E, Count> entry, which can then be used for 1540888a09821a98ac0680fad765217302858e70fa4Paul Duffin * a more efficient remove() call. 1550888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 1560888a09821a98ac0680fad765217302858e70fa4Paul Duffin private class MapBasedMultisetIterator implements Iterator<E> { 1570888a09821a98ac0680fad765217302858e70fa4Paul Duffin final Iterator<Map.Entry<E, Count>> entryIterator; 1580888a09821a98ac0680fad765217302858e70fa4Paul Duffin Map.Entry<E, Count> currentEntry; 1590888a09821a98ac0680fad765217302858e70fa4Paul Duffin int occurrencesLeft; 1600888a09821a98ac0680fad765217302858e70fa4Paul Duffin boolean canRemove; 1610888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1620888a09821a98ac0680fad765217302858e70fa4Paul Duffin MapBasedMultisetIterator() { 1630888a09821a98ac0680fad765217302858e70fa4Paul Duffin this.entryIterator = backingMap.entrySet().iterator(); 1640888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1650888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1660888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 1670888a09821a98ac0680fad765217302858e70fa4Paul Duffin public boolean hasNext() { 1680888a09821a98ac0680fad765217302858e70fa4Paul Duffin return occurrencesLeft > 0 || entryIterator.hasNext(); 1690888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1700888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1710888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 1720888a09821a98ac0680fad765217302858e70fa4Paul Duffin public E next() { 1730888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (occurrencesLeft == 0) { 1740888a09821a98ac0680fad765217302858e70fa4Paul Duffin currentEntry = entryIterator.next(); 1750888a09821a98ac0680fad765217302858e70fa4Paul Duffin occurrencesLeft = currentEntry.getValue().get(); 1760888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1770888a09821a98ac0680fad765217302858e70fa4Paul Duffin occurrencesLeft--; 1780888a09821a98ac0680fad765217302858e70fa4Paul Duffin canRemove = true; 1790888a09821a98ac0680fad765217302858e70fa4Paul Duffin return currentEntry.getKey(); 1800888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1810888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1820888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 1830888a09821a98ac0680fad765217302858e70fa4Paul Duffin public void remove() { 1840888a09821a98ac0680fad765217302858e70fa4Paul Duffin checkRemove(canRemove); 1850888a09821a98ac0680fad765217302858e70fa4Paul Duffin int frequency = currentEntry.getValue().get(); 1860888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (frequency <= 0) { 1870888a09821a98ac0680fad765217302858e70fa4Paul Duffin throw new ConcurrentModificationException(); 1880888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1890888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (currentEntry.getValue().addAndGet(-1) == 0) { 1900888a09821a98ac0680fad765217302858e70fa4Paul Duffin entryIterator.remove(); 1910888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1920888a09821a98ac0680fad765217302858e70fa4Paul Duffin size--; 1930888a09821a98ac0680fad765217302858e70fa4Paul Duffin canRemove = false; 1940888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1950888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1960888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1970888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public int count(@Nullable Object element) { 1980888a09821a98ac0680fad765217302858e70fa4Paul Duffin Count frequency = Maps.safeGet(backingMap, element); 1990888a09821a98ac0680fad765217302858e70fa4Paul Duffin return (frequency == null) ? 0 : frequency.get(); 2000888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 2010888a09821a98ac0680fad765217302858e70fa4Paul Duffin 2020888a09821a98ac0680fad765217302858e70fa4Paul Duffin // Optional Operations - Modification Operations 2030888a09821a98ac0680fad765217302858e70fa4Paul Duffin 2040888a09821a98ac0680fad765217302858e70fa4Paul Duffin /** 2050888a09821a98ac0680fad765217302858e70fa4Paul Duffin * {@inheritDoc} 2060888a09821a98ac0680fad765217302858e70fa4Paul Duffin * 2070888a09821a98ac0680fad765217302858e70fa4Paul Duffin * @throws IllegalArgumentException if the call would result in more than 2080888a09821a98ac0680fad765217302858e70fa4Paul Duffin * {@link Integer#MAX_VALUE} occurrences of {@code element} in this 2090888a09821a98ac0680fad765217302858e70fa4Paul Duffin * multiset. 2100888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 2110888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public int add(@Nullable E element, int occurrences) { 2120888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (occurrences == 0) { 2130888a09821a98ac0680fad765217302858e70fa4Paul Duffin return count(element); 2140888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 2150888a09821a98ac0680fad765217302858e70fa4Paul Duffin checkArgument( 2160888a09821a98ac0680fad765217302858e70fa4Paul Duffin occurrences > 0, "occurrences cannot be negative: %s", occurrences); 2170888a09821a98ac0680fad765217302858e70fa4Paul Duffin Count frequency = backingMap.get(element); 2180888a09821a98ac0680fad765217302858e70fa4Paul Duffin int oldCount; 2190888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (frequency == null) { 2200888a09821a98ac0680fad765217302858e70fa4Paul Duffin oldCount = 0; 2210888a09821a98ac0680fad765217302858e70fa4Paul Duffin backingMap.put(element, new Count(occurrences)); 2220888a09821a98ac0680fad765217302858e70fa4Paul Duffin } else { 2230888a09821a98ac0680fad765217302858e70fa4Paul Duffin oldCount = frequency.get(); 2240888a09821a98ac0680fad765217302858e70fa4Paul Duffin long newCount = (long) oldCount + (long) occurrences; 2250888a09821a98ac0680fad765217302858e70fa4Paul Duffin checkArgument(newCount <= Integer.MAX_VALUE, 2260888a09821a98ac0680fad765217302858e70fa4Paul Duffin "too many occurrences: %s", newCount); 2270888a09821a98ac0680fad765217302858e70fa4Paul Duffin frequency.getAndAdd(occurrences); 2280888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 2290888a09821a98ac0680fad765217302858e70fa4Paul Duffin size += occurrences; 2300888a09821a98ac0680fad765217302858e70fa4Paul Duffin return oldCount; 2310888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 2320888a09821a98ac0680fad765217302858e70fa4Paul Duffin 2330888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public int remove(@Nullable Object element, int occurrences) { 2340888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (occurrences == 0) { 2350888a09821a98ac0680fad765217302858e70fa4Paul Duffin return count(element); 2360888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 2370888a09821a98ac0680fad765217302858e70fa4Paul Duffin checkArgument( 2380888a09821a98ac0680fad765217302858e70fa4Paul Duffin occurrences > 0, "occurrences cannot be negative: %s", occurrences); 2390888a09821a98ac0680fad765217302858e70fa4Paul Duffin Count frequency = backingMap.get(element); 2400888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (frequency == null) { 2410888a09821a98ac0680fad765217302858e70fa4Paul Duffin return 0; 2420888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 2430888a09821a98ac0680fad765217302858e70fa4Paul Duffin 2440888a09821a98ac0680fad765217302858e70fa4Paul Duffin int oldCount = frequency.get(); 2450888a09821a98ac0680fad765217302858e70fa4Paul Duffin 2460888a09821a98ac0680fad765217302858e70fa4Paul Duffin int numberRemoved; 2470888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (oldCount > occurrences) { 2480888a09821a98ac0680fad765217302858e70fa4Paul Duffin numberRemoved = occurrences; 2490888a09821a98ac0680fad765217302858e70fa4Paul Duffin } else { 2500888a09821a98ac0680fad765217302858e70fa4Paul Duffin numberRemoved = oldCount; 2510888a09821a98ac0680fad765217302858e70fa4Paul Duffin backingMap.remove(element); 2520888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 2530888a09821a98ac0680fad765217302858e70fa4Paul Duffin 2540888a09821a98ac0680fad765217302858e70fa4Paul Duffin frequency.addAndGet(-numberRemoved); 2550888a09821a98ac0680fad765217302858e70fa4Paul Duffin size -= numberRemoved; 2560888a09821a98ac0680fad765217302858e70fa4Paul Duffin return oldCount; 2570888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 2580888a09821a98ac0680fad765217302858e70fa4Paul Duffin 2590888a09821a98ac0680fad765217302858e70fa4Paul Duffin // Roughly a 33% performance improvement over AbstractMultiset.setCount(). 2600888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public int setCount(@Nullable E element, int count) { 2610888a09821a98ac0680fad765217302858e70fa4Paul Duffin checkNonnegative(count, "count"); 2620888a09821a98ac0680fad765217302858e70fa4Paul Duffin 2630888a09821a98ac0680fad765217302858e70fa4Paul Duffin Count existingCounter; 2640888a09821a98ac0680fad765217302858e70fa4Paul Duffin int oldCount; 2650888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (count == 0) { 2660888a09821a98ac0680fad765217302858e70fa4Paul Duffin existingCounter = backingMap.remove(element); 2670888a09821a98ac0680fad765217302858e70fa4Paul Duffin oldCount = getAndSet(existingCounter, count); 2680888a09821a98ac0680fad765217302858e70fa4Paul Duffin } else { 2690888a09821a98ac0680fad765217302858e70fa4Paul Duffin existingCounter = backingMap.get(element); 2700888a09821a98ac0680fad765217302858e70fa4Paul Duffin oldCount = getAndSet(existingCounter, count); 2710888a09821a98ac0680fad765217302858e70fa4Paul Duffin 2720888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (existingCounter == null) { 2730888a09821a98ac0680fad765217302858e70fa4Paul Duffin backingMap.put(element, new Count(count)); 2740888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 2750888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 2760888a09821a98ac0680fad765217302858e70fa4Paul Duffin 2770888a09821a98ac0680fad765217302858e70fa4Paul Duffin size += (count - oldCount); 2780888a09821a98ac0680fad765217302858e70fa4Paul Duffin return oldCount; 2790888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 2800888a09821a98ac0680fad765217302858e70fa4Paul Duffin 2810888a09821a98ac0680fad765217302858e70fa4Paul Duffin private static int getAndSet(Count i, int count) { 2820888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (i == null) { 2830888a09821a98ac0680fad765217302858e70fa4Paul Duffin return 0; 2840888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 2850888a09821a98ac0680fad765217302858e70fa4Paul Duffin 2860888a09821a98ac0680fad765217302858e70fa4Paul Duffin return i.getAndSet(count); 2870888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 2880888a09821a98ac0680fad765217302858e70fa4Paul Duffin 2890888a09821a98ac0680fad765217302858e70fa4Paul Duffin // Don't allow default serialization. 2900888a09821a98ac0680fad765217302858e70fa4Paul Duffin} 2910888a09821a98ac0680fad765217302858e70fa4Paul Duffin 292