1 /* 2 * Copyright (C) 2007 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.collect; 18 19 import com.google.common.annotations.GwtCompatible; 20 import static com.google.common.base.Preconditions.checkArgument; 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 import java.util.concurrent.atomic.AtomicInteger; 28 29 /** 30 * Multiset implementation backed by an {@link EnumMap}. 31 * 32 * @author Jared Levy 33 * @since 2010.01.04 <b>stable</b> (imported from Google Collections Library) 34 */ 35 @GwtCompatible 36 public final class EnumMultiset<E extends Enum<E>> 37 extends AbstractMapBasedMultiset<E> { 38 /** Creates an empty {@code EnumMultiset}. */ create(Class<E> type)39 public static <E extends Enum<E>> EnumMultiset<E> create(Class<E> type) { 40 return new EnumMultiset<E>(type); 41 } 42 43 /** 44 * Creates a new {@code EnumMultiset} containing the specified elements. 45 * 46 * @param elements the elements that the multiset should contain 47 * @throws IllegalArgumentException if {@code elements} is empty 48 */ create( Iterable<E> elements)49 public static <E extends Enum<E>> EnumMultiset<E> create( 50 Iterable<E> elements) { 51 Iterator<E> iterator = elements.iterator(); 52 checkArgument(iterator.hasNext(), 53 "EnumMultiset constructor passed empty Iterable"); 54 EnumMultiset<E> multiset 55 = new EnumMultiset<E>(iterator.next().getDeclaringClass()); 56 Iterables.addAll(multiset, elements); 57 return multiset; 58 } 59 60 private transient Class<E> type; 61 62 /** Creates an empty {@code EnumMultiset}. */ EnumMultiset(Class<E> type)63 private EnumMultiset(Class<E> type) { 64 super(new EnumMap<E, AtomicInteger>(type)); 65 this.type = type; 66 } 67 writeObject(ObjectOutputStream stream)68 private void writeObject(ObjectOutputStream stream) throws IOException { 69 stream.defaultWriteObject(); 70 stream.writeObject(type); 71 Serialization.writeMultiset(this, stream); 72 } 73 74 /** 75 * @serialData the {@code Class<E>} for the enum type, the number of distinct 76 * elements, the first element, its count, the second element, its count, 77 * and so on 78 */ readObject(ObjectInputStream stream)79 private void readObject(ObjectInputStream stream) 80 throws IOException, ClassNotFoundException { 81 stream.defaultReadObject(); 82 @SuppressWarnings("unchecked") // reading data stored by writeObject 83 Class<E> localType = (Class<E>) stream.readObject(); 84 type = localType; 85 setBackingMap(new EnumMap<E, AtomicInteger>(type)); 86 Serialization.populateMultiset(this, stream); 87 } 88 89 private static final long serialVersionUID = 0; 90 } 91