Home | History | Annotate | Download | only in collect
      1 /*
      2  * Copyright (C) 2007 The Guava Authors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
      5  * in compliance with the License. You may obtain a copy of the License at
      6  *
      7  * http://www.apache.org/licenses/LICENSE-2.0
      8  *
      9  * Unless required by applicable law or agreed to in writing, software distributed under the License
     10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
     11  * or implied. See the License for the specific language governing permissions and limitations under
     12  * the License.
     13  */
     14 
     15 package com.google.common.collect;
     16 
     17 import static com.google.common.base.Preconditions.checkArgument;
     18 
     19 import com.google.common.annotations.GwtCompatible;
     20 import com.google.common.annotations.GwtIncompatible;
     21 
     22 import java.io.IOException;
     23 import java.io.ObjectInputStream;
     24 import java.io.ObjectOutputStream;
     25 import java.util.EnumMap;
     26 import java.util.Iterator;
     27 
     28 /**
     29  * Multiset implementation backed by an {@link EnumMap}.
     30  *
     31  * <p>See the Guava User Guide article on <a href=
     32  * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
     33  * {@code Multiset}</a>.
     34  *
     35  * @author Jared Levy
     36  * @since 2.0 (imported from Google Collections Library)
     37  */
     38 @GwtCompatible(emulated = true)
     39 public final class EnumMultiset<E extends Enum<E>> extends AbstractMapBasedMultiset<E> {
     40   /** Creates an empty {@code EnumMultiset}. */
     41   public static <E extends Enum<E>> EnumMultiset<E> create(Class<E> type) {
     42     return new EnumMultiset<E>(type);
     43   }
     44 
     45   /**
     46    * Creates a new {@code EnumMultiset} containing the specified elements.
     47    *
     48    * <p>This implementation is highly efficient when {@code elements} is itself a {@link
     49    * Multiset}.
     50    *
     51    * @param elements the elements that the multiset should contain
     52    * @throws IllegalArgumentException if {@code elements} is empty
     53    */
     54   public static <E extends Enum<E>> EnumMultiset<E> create(Iterable<E> elements) {
     55     Iterator<E> iterator = elements.iterator();
     56     checkArgument(iterator.hasNext(), "EnumMultiset constructor passed empty Iterable");
     57     EnumMultiset<E> multiset = new EnumMultiset<E>(iterator.next().getDeclaringClass());
     58     Iterables.addAll(multiset, elements);
     59     return multiset;
     60   }
     61 
     62   /**
     63    * Returns a new {@code EnumMultiset} instance containing the given elements.  Unlike
     64    * {@link EnumMultiset#create(Iterable)}, this method does not produce an exception on an empty
     65    * iterable.
     66    *
     67    * @since 14.0
     68    */
     69   public static <E extends Enum<E>> EnumMultiset<E> create(Iterable<E> elements, Class<E> type) {
     70     EnumMultiset<E> result = create(type);
     71     Iterables.addAll(result, elements);
     72     return result;
     73   }
     74 
     75   private transient Class<E> type;
     76 
     77   /** Creates an empty {@code EnumMultiset}. */
     78   private EnumMultiset(Class<E> type) {
     79     super(WellBehavedMap.wrap(new EnumMap<E, Count>(type)));
     80     this.type = type;
     81   }
     82 
     83   @GwtIncompatible("java.io.ObjectOutputStream")
     84   private void writeObject(ObjectOutputStream stream) throws IOException {
     85     stream.defaultWriteObject();
     86     stream.writeObject(type);
     87     Serialization.writeMultiset(this, stream);
     88   }
     89 
     90   /**
     91    * @serialData the {@code Class<E>} for the enum type, the number of distinct
     92    *             elements, the first element, its count, the second element, its
     93    *             count, and so on
     94    */
     95   @GwtIncompatible("java.io.ObjectInputStream")
     96   private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
     97     stream.defaultReadObject();
     98     @SuppressWarnings("unchecked") // reading data stored by writeObject
     99     Class<E> localType = (Class<E>) stream.readObject();
    100     type = localType;
    101     setBackingMap(WellBehavedMap.wrap(new EnumMap<E, Count>(type)));
    102     Serialization.populateMultiset(this, stream);
    103   }
    104 
    105   @GwtIncompatible("Not needed in emulated source")
    106   private static final long serialVersionUID = 0;
    107 }
    108