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