001 /* 002 * Copyright (C) 2007 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package com.google.common.collect; 018 019 import static com.google.common.base.Preconditions.checkArgument; 020 021 import com.google.common.annotations.GwtCompatible; 022 import com.google.common.annotations.GwtIncompatible; 023 024 import java.io.IOException; 025 import java.io.ObjectInputStream; 026 import java.io.ObjectOutputStream; 027 import java.util.EnumMap; 028 import java.util.Iterator; 029 import java.util.concurrent.atomic.AtomicInteger; 030 031 /** 032 * Multiset implementation backed by an {@link EnumMap}. 033 * 034 * @author Jared Levy 035 * @since 2 (imported from Google Collections Library) 036 */ 037 @GwtCompatible(emulated = true) 038 public final class EnumMultiset<E extends Enum<E>> extends AbstractMapBasedMultiset<E> { 039 /** Creates an empty {@code EnumMultiset}. */ 040 public static <E extends Enum<E>> EnumMultiset<E> create(Class<E> type) { 041 return new EnumMultiset<E>(type); 042 } 043 044 /** 045 * Creates a new {@code EnumMultiset} containing the specified elements. 046 * 047 * @param elements the elements that the multiset should contain 048 * @throws IllegalArgumentException if {@code elements} is empty 049 */ 050 public static <E extends Enum<E>> EnumMultiset<E> create(Iterable<E> elements) { 051 Iterator<E> iterator = elements.iterator(); 052 checkArgument(iterator.hasNext(), "EnumMultiset constructor passed empty Iterable"); 053 EnumMultiset<E> multiset = new EnumMultiset<E>(iterator.next().getDeclaringClass()); 054 Iterables.addAll(multiset, elements); 055 return multiset; 056 } 057 058 private transient Class<E> type; 059 060 /** Creates an empty {@code EnumMultiset}. */ 061 private EnumMultiset(Class<E> type) { 062 super(WellBehavedMap.wrap(new EnumMap<E, AtomicInteger>(type))); 063 this.type = type; 064 } 065 066 @GwtIncompatible("java.io.ObjectOutputStream") 067 private void writeObject(ObjectOutputStream stream) throws IOException { 068 stream.defaultWriteObject(); 069 stream.writeObject(type); 070 Serialization.writeMultiset(this, stream); 071 } 072 073 /** 074 * @serialData the {@code Class<E>} for the enum type, the number of distinct 075 * elements, the first element, its count, the second element, its 076 * count, and so on 077 */ 078 @GwtIncompatible("java.io.ObjectInputStream") 079 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 080 stream.defaultReadObject(); 081 @SuppressWarnings("unchecked") // reading data stored by writeObject 082 Class<E> localType = (Class<E>) stream.readObject(); 083 type = localType; 084 setBackingMap(WellBehavedMap.wrap(new EnumMap<E, AtomicInteger>(type))); 085 Serialization.populateMultiset(this, stream); 086 } 087 088 @GwtIncompatible("Not needed in emulated source") 089 private static final long serialVersionUID = 0; 090 }