1090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2008 The Guava Authors
3090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson *
4090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
5090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * you may not use this file except in compliance with the License.
6090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * You may obtain a copy of the License at
7090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson *
8090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0
9090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson *
10090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Unless required by applicable law or agreed to in writing, software
11090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
12090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * See the License for the specific language governing permissions and
14090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * limitations under the License.
15090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */
16090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
17090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonpackage com.google.common.collect;
18090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
19090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport static com.google.common.base.Preconditions.checkNotNull;
20090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtCompatible;
220888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.annotations.GwtIncompatible;
230888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.collect.Multiset.Entry;
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.primitives.Ints;
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.io.Serializable;
27090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.Arrays;
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Collection;
29090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.Iterator;
30090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
31090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport javax.annotation.Nullable;
32090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
33090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson/**
34090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * An immutable hash-based multiset. Does not permit null elements.
35090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson *
36090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * <p>Its iterator orders elements according to the first appearance of the
37090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * element among the items passed to the factory method or builder. When the
38090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * multiset contains multiple instances of an element, those instances are
39090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * consecutive in the iteration order.
40090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson *
417dd252788645e940eada959bdde927426e2531c9Paul Duffin * <p>See the Guava User Guide article on <a href=
427dd252788645e940eada959bdde927426e2531c9Paul Duffin * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
437dd252788645e940eada959bdde927426e2531c9Paul Duffin * immutable collections</a>.
447dd252788645e940eada959bdde927426e2531c9Paul Duffin *
45090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @author Jared Levy
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Louis Wasserman
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 2.0 (imported from Google Collections Library)
48090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */
490888a09821a98ac0680fad765217302858e70fa4Paul Duffin@GwtCompatible(serializable = true, emulated = true)
500888a09821a98ac0680fad765217302858e70fa4Paul Duffin@SuppressWarnings("serial") // we're overriding default serialization
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// TODO(user): write an efficient asList() implementation
520888a09821a98ac0680fad765217302858e70fa4Paul Duffinpublic abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
530888a09821a98ac0680fad765217302858e70fa4Paul Duffin    implements Multiset<E> {
540888a09821a98ac0680fad765217302858e70fa4Paul Duffin
550888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static final ImmutableMultiset<Object> EMPTY =
560888a09821a98ac0680fad765217302858e70fa4Paul Duffin      new RegularImmutableMultiset<Object>(ImmutableMap.<Object, Integer>of(), 0);
57090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
58090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
59090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Returns the empty immutable multiset.
60090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
610888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @SuppressWarnings("unchecked") // all supported methods are covariant
62090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  public static <E> ImmutableMultiset<E> of() {
630888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return (ImmutableMultiset<E>) EMPTY;
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns an immutable multiset containing a single element.
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @throws NullPointerException if {@code element} is null
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @since 6.0 (source-compatible since 2.0)
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
720888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @SuppressWarnings("unchecked") // generic array created but never written
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static <E> ImmutableMultiset<E> of(E element) {
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return copyOfInternal(element);
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns an immutable multiset containing the given elements, in order.
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @throws NullPointerException if any element is null
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @since 6.0 (source-compatible since 2.0)
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
830888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @SuppressWarnings("unchecked") //
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static <E> ImmutableMultiset<E> of(E e1, E e2) {
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return copyOfInternal(e1, e2);
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns an immutable multiset containing the given elements, in order.
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @throws NullPointerException if any element is null
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @since 6.0 (source-compatible since 2.0)
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
940888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @SuppressWarnings("unchecked") //
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3) {
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return copyOfInternal(e1, e2, e3);
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns an immutable multiset containing the given elements, in order.
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @throws NullPointerException if any element is null
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @since 6.0 (source-compatible since 2.0)
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1050888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @SuppressWarnings("unchecked") //
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3, E e4) {
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return copyOfInternal(e1, e2, e3, e4);
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns an immutable multiset containing the given elements, in order.
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @throws NullPointerException if any element is null
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @since 6.0 (source-compatible since 2.0)
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1160888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @SuppressWarnings("unchecked") //
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3, E e4, E e5) {
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return copyOfInternal(e1, e2, e3, e4, e5);
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns an immutable multiset containing the given elements, in order.
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @throws NullPointerException if any element is null
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @since 6.0 (source-compatible since 2.0)
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1270888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @SuppressWarnings("unchecked") //
1280888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public static <E> ImmutableMultiset<E> of(
1290888a09821a98ac0680fad765217302858e70fa4Paul Duffin      E e1, E e2, E e3, E e4, E e5, E e6, E... others) {
1300888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return new Builder<E>()
1310888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .add(e1)
1320888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .add(e2)
1330888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .add(e3)
1340888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .add(e4)
1350888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .add(e5)
1360888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .add(e6)
1370888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .add(others)
1380888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .build();
139090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
140090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
141090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
142090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Returns an immutable multiset containing the given elements.
143090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
144090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * <p>The multiset is ordered by the first occurrence of each element. For
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * example, {@code ImmutableMultiset.copyOf([2, 3, 1, 3])} yields a multiset
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * with elements in the order {@code 2, 3, 3, 1}.
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @throws NullPointerException if any of {@code elements} is null
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @since 6.0
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static <E> ImmutableMultiset<E> copyOf(E[] elements) {
152090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return copyOf(Arrays.asList(elements));
153090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
154090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
155090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
156090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Returns an immutable multiset containing the given elements.
157090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
158090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * <p>The multiset is ordered by the first occurrence of each element. For
159090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * example, {@code ImmutableMultiset.copyOf(Arrays.asList(2, 3, 1, 3))} yields
160090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * a multiset with elements in the order {@code 2, 3, 3, 1}.
161090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>Despite the method name, this method attempts to avoid actually copying
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * the data when it is safe to do so. The exact circumstances under which a
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * copy will or will not be performed are undocumented and subject to change.
165090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
166090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * <p><b>Note:</b> Despite what the method name suggests, if {@code elements}
167090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * is an {@code ImmutableMultiset}, no copy will actually be performed, and
168090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * the given multiset itself will be returned.
169090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
170090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * @throws NullPointerException if any of {@code elements} is null
171090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
1720888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public static <E> ImmutableMultiset<E> copyOf(
1730888a09821a98ac0680fad765217302858e70fa4Paul Duffin      Iterable<? extends E> elements) {
174090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    if (elements instanceof ImmutableMultiset) {
1750888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @SuppressWarnings("unchecked") // all supported methods are covariant
176090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      ImmutableMultiset<E> result = (ImmutableMultiset<E>) elements;
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!result.isPartialView()) {
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return result;
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
180090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
181090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
1820888a09821a98ac0680fad765217302858e70fa4Paul Duffin    Multiset<? extends E> multiset = (elements instanceof Multiset)
1830888a09821a98ac0680fad765217302858e70fa4Paul Duffin        ? Multisets.cast(elements)
184090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        : LinkedHashMultiset.create(elements);
185090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
186090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return copyOfInternal(multiset);
187090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
188090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static <E> ImmutableMultiset<E> copyOfInternal(E... elements) {
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return copyOf(Arrays.asList(elements));
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1930888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static <E> ImmutableMultiset<E> copyOfInternal(
1940888a09821a98ac0680fad765217302858e70fa4Paul Duffin      Multiset<? extends E> multiset) {
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return copyFromEntries(multiset.entrySet());
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1980888a09821a98ac0680fad765217302858e70fa4Paul Duffin  static <E> ImmutableMultiset<E> copyFromEntries(
1990888a09821a98ac0680fad765217302858e70fa4Paul Duffin      Collection<? extends Entry<? extends E>> entries) {
200090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    long size = 0;
201090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    ImmutableMap.Builder<E, Integer> builder = ImmutableMap.builder();
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (Entry<? extends E> entry : entries) {
203090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      int count = entry.getCount();
204090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      if (count > 0) {
205090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        // Since ImmutableMap.Builder throws an NPE if an element is null, no
206090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        // other null checks are needed.
207090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        builder.put(entry.getElement(), count);
208090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        size += count;
209090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      }
210090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
211090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
212090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    if (size == 0) {
213090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return of();
214090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
2150888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return new RegularImmutableMultiset<E>(
2160888a09821a98ac0680fad765217302858e70fa4Paul Duffin        builder.build(), Ints.saturatedCast(size));
217090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
218090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
219090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
220090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Returns an immutable multiset containing the given elements.
221090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
222090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * <p>The multiset is ordered by the first occurrence of each element. For
223090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * example,
224090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * {@code ImmutableMultiset.copyOf(Arrays.asList(2, 3, 1, 3).iterator())}
225090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * yields a multiset with elements in the order {@code 2, 3, 3, 1}.
226090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
227090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * @throws NullPointerException if any of {@code elements} is null
228090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
2290888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public static <E> ImmutableMultiset<E> copyOf(
2300888a09821a98ac0680fad765217302858e70fa4Paul Duffin      Iterator<? extends E> elements) {
231090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    Multiset<E> multiset = LinkedHashMultiset.create();
232090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    Iterators.addAll(multiset, elements);
233090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return copyOfInternal(multiset);
234090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
235090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  ImmutableMultiset() {}
237090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
2380888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override public UnmodifiableIterator<E> iterator() {
2397dd252788645e940eada959bdde927426e2531c9Paul Duffin    final Iterator<Entry<E>> entryIterator = entrySet().iterator();
240090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return new UnmodifiableIterator<E>() {
241090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      int remaining;
242090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      E element;
243090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
2440888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override
245090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      public boolean hasNext() {
2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return (remaining > 0) || entryIterator.hasNext();
247090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      }
248090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
2490888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override
250090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      public E next() {
251090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        if (remaining <= 0) {
2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Entry<E> entry = entryIterator.next();
2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          element = entry.getElement();
2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          remaining = entry.getCount();
255090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        }
256090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        remaining--;
257090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        return element;
258090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      }
259090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    };
260090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
261090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean contains(@Nullable Object object) {
2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return count(object) > 0;
265090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
266090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean containsAll(Collection<?> targets) {
2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return elementSet().containsAll(targets);
270090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
271090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
272090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
273090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Guaranteed to throw an exception and leave the collection unmodified.
274090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
275090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * @throws UnsupportedOperationException always
2767dd252788645e940eada959bdde927426e2531c9Paul Duffin   * @deprecated Unsupported operation.
277090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
2787dd252788645e940eada959bdde927426e2531c9Paul Duffin  @Deprecated
2790888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override
2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public final int add(E element, int occurrences) {
281090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    throw new UnsupportedOperationException();
282090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
283090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
284090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
285090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Guaranteed to throw an exception and leave the collection unmodified.
286090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
287090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * @throws UnsupportedOperationException always
2887dd252788645e940eada959bdde927426e2531c9Paul Duffin   * @deprecated Unsupported operation.
289090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
2907dd252788645e940eada959bdde927426e2531c9Paul Duffin  @Deprecated
2910888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override
2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public final int remove(Object element, int occurrences) {
293090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    throw new UnsupportedOperationException();
294090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
295090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
296090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
297090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Guaranteed to throw an exception and leave the collection unmodified.
298090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
299090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * @throws UnsupportedOperationException always
3007dd252788645e940eada959bdde927426e2531c9Paul Duffin   * @deprecated Unsupported operation.
301090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
3027dd252788645e940eada959bdde927426e2531c9Paul Duffin  @Deprecated
3030888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override
3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public final int setCount(E element, int count) {
305090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    throw new UnsupportedOperationException();
306090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
307090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
308090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
309090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Guaranteed to throw an exception and leave the collection unmodified.
310090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
311090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * @throws UnsupportedOperationException always
3127dd252788645e940eada959bdde927426e2531c9Paul Duffin   * @deprecated Unsupported operation.
313090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
3147dd252788645e940eada959bdde927426e2531c9Paul Duffin  @Deprecated
3150888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override
3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public final boolean setCount(E element, int oldCount, int newCount) {
317090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    throw new UnsupportedOperationException();
318090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
319090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
3200888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @GwtIncompatible("not present in emulated superclass")
3217dd252788645e940eada959bdde927426e2531c9Paul Duffin  @Override
3220888a09821a98ac0680fad765217302858e70fa4Paul Duffin  int copyIntoArray(Object[] dst, int offset) {
3230888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (Multiset.Entry<E> entry : entrySet()) {
3240888a09821a98ac0680fad765217302858e70fa4Paul Duffin      Arrays.fill(dst, offset, offset + entry.getCount(), entry.getElement());
3250888a09821a98ac0680fad765217302858e70fa4Paul Duffin      offset += entry.getCount();
326090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
3270888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return offset;
328090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
329090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
3300888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override public boolean equals(@Nullable Object object) {
3310888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return Multisets.equalsImpl(this, object);
3320888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
3330888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3340888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override public int hashCode() {
3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return Sets.hashCodeImpl(entrySet());
336090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
337090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
3380888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override public String toString() {
339090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return entrySet().toString();
340090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
341090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
342090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  private transient ImmutableSet<Entry<E>> entrySet;
343090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
3440888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override
3457dd252788645e940eada959bdde927426e2531c9Paul Duffin  public ImmutableSet<Entry<E>> entrySet() {
346090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    ImmutableSet<Entry<E>> es = entrySet;
3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (es == null) ? (entrySet = createEntrySet()) : es;
348090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
349090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
3500888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private final ImmutableSet<Entry<E>> createEntrySet() {
3510888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return isEmpty() ? ImmutableSet.<Entry<E>>of() : new EntrySet();
3520888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
353dbd967a6e5c96cc1a97c5521f88dc1564ba2f81bPaul Duffin
3540888a09821a98ac0680fad765217302858e70fa4Paul Duffin  abstract Entry<E> getEntry(int index);
3551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3560888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private final class EntrySet extends ImmutableSet<Entry<E>> {
3571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
3581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean isPartialView() {
3597dd252788645e940eada959bdde927426e2531c9Paul Duffin      return ImmutableMultiset.this.isPartialView();
360090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
361090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
3621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
3630888a09821a98ac0680fad765217302858e70fa4Paul Duffin    public UnmodifiableIterator<Entry<E>> iterator() {
3640888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return asList().iterator();
3650888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
3660888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3670888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override
3680888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ImmutableList<Entry<E>> createAsList() {
3690888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return new ImmutableAsList<Entry<E>>() {
3700888a09821a98ac0680fad765217302858e70fa4Paul Duffin        @Override
3710888a09821a98ac0680fad765217302858e70fa4Paul Duffin        public Entry<E> get(int index) {
3720888a09821a98ac0680fad765217302858e70fa4Paul Duffin          return getEntry(index);
3730888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
3740888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3750888a09821a98ac0680fad765217302858e70fa4Paul Duffin        @Override
3760888a09821a98ac0680fad765217302858e70fa4Paul Duffin        ImmutableCollection<Entry<E>> delegateCollection() {
3770888a09821a98ac0680fad765217302858e70fa4Paul Duffin          return EntrySet.this;
3780888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
3790888a09821a98ac0680fad765217302858e70fa4Paul Duffin      };
3800888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
3810888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3820888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override
3830888a09821a98ac0680fad765217302858e70fa4Paul Duffin    public int size() {
3840888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return elementSet().size();
3850888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
3860888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3870888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override
3881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean contains(Object o) {
389090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      if (o instanceof Entry) {
390090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        Entry<?> entry = (Entry<?>) o;
391090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        if (entry.getCount() <= 0) {
392090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson          return false;
393090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        }
3947dd252788645e940eada959bdde927426e2531c9Paul Duffin        int count = count(entry.getElement());
395090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        return count == entry.getCount();
396090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      }
397090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return false;
398090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
399090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
4001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
4011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int hashCode() {
4027dd252788645e940eada959bdde927426e2531c9Paul Duffin      return ImmutableMultiset.this.hashCode();
4031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4050888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // We can't label this with @Override, because it doesn't override anything
4061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // in the GWT emulated version.
4077dd252788645e940eada959bdde927426e2531c9Paul Duffin    // TODO(cpovirk): try making all copies of this method @GwtIncompatible instead
4081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Object writeReplace() {
4097dd252788645e940eada959bdde927426e2531c9Paul Duffin      return new EntrySetSerializedForm<E>(ImmutableMultiset.this);
4101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4127dd252788645e940eada959bdde927426e2531c9Paul Duffin    private static final long serialVersionUID = 0;
4137dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4157dd252788645e940eada959bdde927426e2531c9Paul Duffin  static class EntrySetSerializedForm<E> implements Serializable {
4167dd252788645e940eada959bdde927426e2531c9Paul Duffin    final ImmutableMultiset<E> multiset;
4171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4187dd252788645e940eada959bdde927426e2531c9Paul Duffin    EntrySetSerializedForm(ImmutableMultiset<E> multiset) {
4197dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.multiset = multiset;
420090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
421090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
4227dd252788645e940eada959bdde927426e2531c9Paul Duffin    Object readResolve() {
4237dd252788645e940eada959bdde927426e2531c9Paul Duffin      return multiset.entrySet();
4247dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
425090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
426090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
4271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static class SerializedForm implements Serializable {
4281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Object[] elements;
4291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final int[] counts;
4301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    SerializedForm(Multiset<?> multiset) {
4321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int distinct = multiset.entrySet().size();
4331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      elements = new Object[distinct];
4341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      counts = new int[distinct];
4351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int i = 0;
4361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (Entry<?> entry : multiset.entrySet()) {
4371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        elements[i] = entry.getElement();
4381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        counts[i] = entry.getCount();
4391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        i++;
4401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
442090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
4431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Object readResolve() {
4440888a09821a98ac0680fad765217302858e70fa4Paul Duffin      LinkedHashMultiset<Object> multiset =
4450888a09821a98ac0680fad765217302858e70fa4Paul Duffin          LinkedHashMultiset.create(elements.length);
4461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (int i = 0; i < elements.length; i++) {
4471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        multiset.add(elements[i], counts[i]);
448090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      }
4491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return ImmutableMultiset.copyOf(multiset);
450090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
451090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
4521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private static final long serialVersionUID = 0;
453090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
454090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
4550888a09821a98ac0680fad765217302858e70fa4Paul Duffin  // We can't label this with @Override, because it doesn't override anything
4561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // in the GWT emulated version.
4571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  Object writeReplace() {
4581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new SerializedForm(this);
459090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
460090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
461090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
462090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Returns a new builder. The generated builder is equivalent to the builder
463090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * created by the {@link Builder} constructor.
464090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
465090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  public static <E> Builder<E> builder() {
466090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return new Builder<E>();
467090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
468090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
469090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
4701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * A builder for creating immutable multiset instances, especially {@code
4711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * public static final} multisets ("constant multisets"). Example:
4721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <pre> {@code
473090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
4741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *   public static final ImmutableMultiset<Bean> BEANS =
4751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *       new ImmutableMultiset.Builder<Bean>()
476090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *           .addCopies(Bean.COCOA, 4)
477090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *           .addCopies(Bean.GARDEN, 6)
478090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *           .addCopies(Bean.RED, 8)
479090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *           .addCopies(Bean.BLACK_EYED, 10)
480090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *           .build();}</pre>
481090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
4820888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * <p>Builder instances can be reused; it is safe to call {@link #build} multiple
4831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * times to build multiple multisets in series.
4841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
4851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @since 2.0 (imported from Google Collections Library)
486090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
4871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static class Builder<E> extends ImmutableCollection.Builder<E> {
4881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Multiset<E> contents;
489090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
490090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    /**
491090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * Creates a new builder. The returned builder is equivalent to the builder
492090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * generated by {@link ImmutableMultiset#builder}.
493090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     */
4941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public Builder() {
4950888a09821a98ac0680fad765217302858e70fa4Paul Duffin      this(LinkedHashMultiset.<E>create());
4961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Builder(Multiset<E> contents) {
4991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.contents = contents;
5001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
501090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
502090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    /**
503090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * Adds {@code element} to the {@code ImmutableMultiset}.
504090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *
505090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @param element the element to add
506090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @return this {@code Builder} object
507090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @throws NullPointerException if {@code element} is null
508090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     */
5090888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public Builder<E> add(E element) {
510090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      contents.add(checkNotNull(element));
511090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return this;
512090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
513090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
514090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    /**
515090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * Adds a number of occurrences of an element to this {@code
516090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * ImmutableMultiset}.
517090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *
518090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @param element the element to add
519090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @param occurrences the number of occurrences of the element to add. May
520090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *     be zero, in which case no change will be made.
521090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @return this {@code Builder} object
522090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @throws NullPointerException if {@code element} is null
523090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @throws IllegalArgumentException if {@code occurrences} is negative, or
524090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *     if this operation would result in more than {@link Integer#MAX_VALUE}
525090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *     occurrences of the element
526090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     */
527090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    public Builder<E> addCopies(E element, int occurrences) {
528090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      contents.add(checkNotNull(element), occurrences);
529090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return this;
530090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
531090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
532090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    /**
533090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * Adds or removes the necessary occurrences of an element such that the
534090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * element attains the desired count.
535090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *
536090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @param element the element to add or remove occurrences of
537090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @param count the desired count of the element in this multiset
538090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @return this {@code Builder} object
539090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @throws NullPointerException if {@code element} is null
540090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @throws IllegalArgumentException if {@code count} is negative
541090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     */
542090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    public Builder<E> setCount(E element, int count) {
543090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      contents.setCount(checkNotNull(element), count);
544090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return this;
545090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
546090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
547090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    /**
548090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * Adds each element of {@code elements} to the {@code ImmutableMultiset}.
549090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *
550090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @param elements the elements to add
551090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @return this {@code Builder} object
552090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @throws NullPointerException if {@code elements} is null or contains a
553090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *     null element
554090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     */
5550888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public Builder<E> add(E... elements) {
556090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      super.add(elements);
557090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return this;
558090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
559090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
560090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    /**
561090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * Adds each element of {@code elements} to the {@code ImmutableMultiset}.
562090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *
563090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @param elements the {@code Iterable} to add to the {@code
564090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *     ImmutableMultiset}
565090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @return this {@code Builder} object
566090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @throws NullPointerException if {@code elements} is null or contains a
567090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *     null element
568090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     */
5690888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public Builder<E> addAll(Iterable<? extends E> elements) {
570090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      if (elements instanceof Multiset) {
5711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Multiset<? extends E> multiset = Multisets.cast(elements);
572090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        for (Entry<? extends E> entry : multiset.entrySet()) {
573090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson          addCopies(entry.getElement(), entry.getCount());
574090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        }
575090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      } else {
576090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        super.addAll(elements);
577090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      }
578090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return this;
579090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
580090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
581090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    /**
582090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * Adds each element of {@code elements} to the {@code ImmutableMultiset}.
583090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *
584090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @param elements the elements to add to the {@code ImmutableMultiset}
585090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @return this {@code Builder} object
586090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @throws NullPointerException if {@code elements} is null or contains a
587090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *     null element
588090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     */
5890888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public Builder<E> addAll(Iterator<? extends E> elements) {
590090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      super.addAll(elements);
591090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return this;
592090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
593090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
594090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    /**
595090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * Returns a newly-created {@code ImmutableMultiset} based on the contents
596090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * of the {@code Builder}.
597090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     */
5980888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public ImmutableMultiset<E> build() {
599090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return copyOf(contents);
600090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
601090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
602090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson}
603