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.
34090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson *
35090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @author Kevin Bourrillion
36090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @author Jared Levy
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 2.0 (imported from Google Collections Library)
38090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible(serializable = true, emulated = true)
40090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson@SuppressWarnings("serial") // we're overriding default serialization
41090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonpublic final class LinkedHashMultiset<E> extends AbstractMapBasedMultiset<E> {
42090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
43090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
44090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Creates a new, empty {@code LinkedHashMultiset} using the default initial
45090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * capacity.
46090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
47090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  public static <E> LinkedHashMultiset<E> create() {
48090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return new LinkedHashMultiset<E>();
49090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
50090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
51090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
52090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Creates a new, empty {@code LinkedHashMultiset} with the specified expected
53090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * number of distinct elements.
54090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
55090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * @param distinctElements the expected number of distinct elements
56090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * @throws IllegalArgumentException if {@code distinctElements} is negative
57090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
58090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  public static <E> LinkedHashMultiset<E> create(int distinctElements) {
59090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return new LinkedHashMultiset<E>(distinctElements);
60090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
61090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
62090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
63090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Creates a new {@code LinkedHashMultiset} containing the specified elements.
64090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>This implementation is highly efficient when {@code elements} is itself
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * a {@link Multiset}.
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
68090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * @param elements the elements that the multiset should contain
69090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
70090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  public static <E> LinkedHashMultiset<E> create(
71090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      Iterable<? extends E> elements) {
72090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    LinkedHashMultiset<E> multiset =
73090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        create(Multisets.inferDistinctElements(elements));
74090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    Iterables.addAll(multiset, elements);
75090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return multiset;
76090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
77090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
78090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  private LinkedHashMultiset() {
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    super(new LinkedHashMap<E, Count>());
80090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
81090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
82090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  private LinkedHashMultiset(int distinctElements) {
83090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    // Could use newLinkedHashMapWithExpectedSize() if it existed
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    super(new LinkedHashMap<E, Count>(Maps.capacity(distinctElements)));
85090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
86090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
87090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
88090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * @serialData the number of distinct elements, the first element, its count,
89090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *     the second element, its count, and so on
90090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("java.io.ObjectOutputStream")
92090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  private void writeObject(ObjectOutputStream stream) throws IOException {
93090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    stream.defaultWriteObject();
94090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    Serialization.writeMultiset(this, stream);
95090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
96090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("java.io.ObjectInputStream")
98090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  private void readObject(ObjectInputStream stream)
99090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      throws IOException, ClassNotFoundException {
100090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    stream.defaultReadObject();
101090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    int distinctElements = Serialization.readCount(stream);
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    setBackingMap(new LinkedHashMap<E, Count>(
103090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        Maps.capacity(distinctElements)));
104090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    Serialization.populateMultiset(this, stream, distinctElements);
105090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
106090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("not needed in emulated source")
108090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  private static final long serialVersionUID = 0;
109090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson}
110