1090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2007 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 com.google.common.annotations.GwtCompatible;
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtIncompatible;
21090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
22090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.io.IOException;
23090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.io.ObjectInputStream;
24090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.io.ObjectOutputStream;
25090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.LinkedHashMap;
26090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
27090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson/**
28090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * A {@code Multiset} implementation with predictable iteration order. Its
29090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * iterator orders elements according to when the first occurrence of the
30090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * element was added. When the multiset contains multiple instances of an
31090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * element, those instances are consecutive in the iteration order. If all
32090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * occurrences of an element are removed, after which that element is added to
33090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * the multiset, the element will appear at the end of the iteration.
347dd252788645e940eada959bdde927426e2531c9Paul Duffin *
357dd252788645e940eada959bdde927426e2531c9Paul Duffin * <p>See the Guava User Guide article on <a href=
367dd252788645e940eada959bdde927426e2531c9Paul Duffin * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
377dd252788645e940eada959bdde927426e2531c9Paul Duffin * {@code Multiset}</a>.
38090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson *
39090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @author Kevin Bourrillion
40090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @author Jared Levy
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 2.0 (imported from Google Collections Library)
42090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible(serializable = true, emulated = true)
440888a09821a98ac0680fad765217302858e70fa4Paul Duffin@SuppressWarnings("serial") // we're overriding default serialization
45090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonpublic final class LinkedHashMultiset<E> extends AbstractMapBasedMultiset<E> {
46090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
47090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
48090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Creates a new, empty {@code LinkedHashMultiset} using the default initial
49090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * capacity.
50090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
51090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  public static <E> LinkedHashMultiset<E> create() {
52090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return new LinkedHashMultiset<E>();
53090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
54090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
55090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
56090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Creates a new, empty {@code LinkedHashMultiset} with the specified expected
57090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * number of distinct elements.
58090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
59090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * @param distinctElements the expected number of distinct elements
60090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * @throws IllegalArgumentException if {@code distinctElements} is negative
61090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
62090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  public static <E> LinkedHashMultiset<E> create(int distinctElements) {
63090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return new LinkedHashMultiset<E>(distinctElements);
64090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
65090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
66090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
67090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Creates a new {@code LinkedHashMultiset} containing the specified elements.
68090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>This implementation is highly efficient when {@code elements} is itself
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * a {@link Multiset}.
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
72090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * @param elements the elements that the multiset should contain
73090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
740888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public static <E> LinkedHashMultiset<E> create(
750888a09821a98ac0680fad765217302858e70fa4Paul Duffin      Iterable<? extends E> elements) {
760888a09821a98ac0680fad765217302858e70fa4Paul Duffin    LinkedHashMultiset<E> multiset =
770888a09821a98ac0680fad765217302858e70fa4Paul Duffin        create(Multisets.inferDistinctElements(elements));
78090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    Iterables.addAll(multiset, elements);
79090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return multiset;
80090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
81090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
82090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  private LinkedHashMultiset() {
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    super(new LinkedHashMap<E, Count>());
84090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
85090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
86090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  private LinkedHashMultiset(int distinctElements) {
87090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    // Could use newLinkedHashMapWithExpectedSize() if it existed
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    super(new LinkedHashMap<E, Count>(Maps.capacity(distinctElements)));
89090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
90090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
91090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
92090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * @serialData the number of distinct elements, the first element, its count,
93090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *     the second element, its count, and so on
94090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("java.io.ObjectOutputStream")
96090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  private void writeObject(ObjectOutputStream stream) throws IOException {
97090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    stream.defaultWriteObject();
98090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    Serialization.writeMultiset(this, stream);
99090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
100090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("java.io.ObjectInputStream")
1020888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private void readObject(ObjectInputStream stream)
1030888a09821a98ac0680fad765217302858e70fa4Paul Duffin      throws IOException, ClassNotFoundException {
104090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    stream.defaultReadObject();
105090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    int distinctElements = Serialization.readCount(stream);
1060888a09821a98ac0680fad765217302858e70fa4Paul Duffin    setBackingMap(new LinkedHashMap<E, Count>(
1070888a09821a98ac0680fad765217302858e70fa4Paul Duffin        Maps.capacity(distinctElements)));
108090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    Serialization.populateMultiset(this, stream, distinctElements);
109090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
110090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("not needed in emulated source")
112090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  private static final long serialVersionUID = 0;
113090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson}
114