• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  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 package java.util;
17 
18 import java.io.Serializable;
19 
20 /**
21  * An EnumSet is a specialized Set to be used with enums as keys.
22  */
23 public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E>
24         implements Cloneable, Serializable {
25     private static final long serialVersionUID = 1009687484059888093L;
26 
27     final Class<E> elementClass;
28 
EnumSet(Class<E> cls)29     EnumSet(Class<E> cls) {
30         elementClass = cls;
31     }
32 
33     /**
34      * Creates an empty enum set. The permitted elements are of type
35      * Class&lt;E&gt;.
36      *
37      * @param elementType
38      *            the class object for the elements contained.
39      * @return an empty enum set, with permitted elements of type {@code
40      *         elementType}.
41      * @throws ClassCastException
42      *             if the specified element type is not and enum type.
43      */
noneOf(Class<E> elementType)44     public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
45         if (!elementType.isEnum()) {
46             throw new ClassCastException(elementType.getClass().getName() + " is not an Enum");
47         }
48         E[] enums = Enum.getSharedConstants(elementType);
49         if (enums.length <= 64) {
50             return new MiniEnumSet<E>(elementType, enums);
51         }
52         return new HugeEnumSet<E>(elementType, enums);
53     }
54 
55     /**
56      * Creates an enum set filled with all the enum elements of the specified
57      * {@code elementType}.
58      *
59      * @param elementType
60      *            the class object for the elements contained.
61      * @return an enum set with elements solely from the specified element type.
62      * @throws ClassCastException
63      *             if the specified element type is not and enum type.
64      */
allOf(Class<E> elementType)65     public static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType) {
66         EnumSet<E> set = noneOf(elementType);
67         set.complement();
68         return set;
69     }
70 
71     /**
72      * Creates an enum set. All the contained elements are of type
73      * Class&lt;E&gt;, and the contained elements are the same as those
74      * contained in {@code s}.
75      *
76      * @param s
77      *            the enum set from which to copy.
78      * @return an enum set with all the elements from the specified enum set.
79      * @throws ClassCastException
80      *             if the specified element type is not and enum type.
81      */
copyOf(EnumSet<E> s)82     public static <E extends Enum<E>> EnumSet<E> copyOf(EnumSet<E> s) {
83         EnumSet<E> set = EnumSet.noneOf(s.elementClass);
84         set.addAll(s);
85         return set;
86     }
87 
88     /**
89      * Creates an enum set. The contained elements are the same as those
90      * contained in collection {@code c}. If c is an enum set, invoking this
91      * method is the same as invoking {@link #copyOf(EnumSet)}.
92      *
93      * @param c
94      *            the collection from which to copy. if it is not an enum set,
95      *            it must not be empty.
96      * @return an enum set with all the elements from the specified collection.
97      * @throws IllegalArgumentException
98      *             if c is not an enum set and contains no elements at all.
99      * @throws NullPointerException
100      *             if {@code c} is {@code null}.
101      */
copyOf(Collection<E> c)102     public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c) {
103         if (c instanceof EnumSet) {
104             return copyOf((EnumSet<E>) c);
105         }
106         if (c.isEmpty()) {
107             throw new IllegalArgumentException();
108         }
109         Iterator<E> iterator = c.iterator();
110         E element = iterator.next();
111         EnumSet<E> set = EnumSet.noneOf(element.getDeclaringClass());
112         set.add(element);
113         while (iterator.hasNext()) {
114             set.add(iterator.next());
115         }
116         return set;
117     }
118 
119     /**
120      * Creates an enum set. All the contained elements complement those from the
121      * specified enum set.
122      *
123      * @param s
124      *            the specified enum set.
125      * @return an enum set with all the elements complementary to those from the
126      *         specified enum set.
127      * @throws NullPointerException
128      *             if {@code s} is {@code null}.
129      */
complementOf(EnumSet<E> s)130     public static <E extends Enum<E>> EnumSet<E> complementOf(EnumSet<E> s) {
131         EnumSet<E> set = EnumSet.noneOf(s.elementClass);
132         set.addAll(s);
133         set.complement();
134         return set;
135     }
136 
complement()137     abstract void complement();
138 
139     /**
140      * Creates a new enum set, containing only the specified element. There are
141      * six overloadings of the method. They accept from one to five elements
142      * respectively. The sixth one receives an arbitrary number of elements, and
143      * runs slower than those that only receive a fixed number of elements.
144      *
145      * @param e
146      *            the element to be initially contained.
147      * @return an enum set containing the specified element.
148      * @throws NullPointerException
149      *             if {@code e} is {@code null}.
150      */
of(E e)151     public static <E extends Enum<E>> EnumSet<E> of(E e) {
152         EnumSet<E> set = EnumSet.noneOf(e.getDeclaringClass());
153         set.add(e);
154         return set;
155     }
156 
157     /**
158      * Creates a new enum set, containing only the specified elements. There are
159      * six overloadings of the method. They accept from one to five elements
160      * respectively. The sixth one receives an arbitrary number of elements, and
161      * runs slower than those that only receive a fixed number of elements.
162      *
163      * @param e1
164      *            the initially contained element.
165      * @param e2
166      *            another initially contained element.
167      * @return an enum set containing the specified elements.
168      * @throws NullPointerException
169      *             if any of the specified elements is {@code null}.
170      */
of(E e1, E e2)171     public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2) {
172         EnumSet<E> set = of(e1);
173         set.add(e2);
174         return set;
175     }
176 
177     /**
178      * Creates a new enum set, containing only the specified elements. There are
179      * six overloadings of the method. They accept from one to five elements
180      * respectively. The sixth one receives an arbitrary number of elements, and
181      * runs slower than those that only receive a fixed number of elements.
182      *
183      * @param e1
184      *            the initially contained element.
185      * @param e2
186      *            another initially contained element.
187      * @param e3
188      *            another initially contained element.
189      * @return an enum set containing the specified elements.
190      * @throws NullPointerException
191      *             if any of the specified elements is {@code null}.
192      */
of(E e1, E e2, E e3)193     public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3) {
194         EnumSet<E> set = of(e1, e2);
195         set.add(e3);
196         return set;
197     }
198 
199     /**
200      * Creates a new enum set, containing only the specified elements. There are
201      * six overloadings of the method. They accept from one to five elements
202      * respectively. The sixth one receives an arbitrary number of elements, and
203      * runs slower than those that only receive a fixed number of elements.
204      *
205      * @param e1
206      *            the initially contained element.
207      * @param e2
208      *            another initially contained element.
209      * @param e3
210      *            another initially contained element.
211      * @param e4
212      *            another initially contained element.
213      * @return an enum set containing the specified elements.
214      * @throws NullPointerException
215      *             if any of the specified elements is {@code null}.
216      */
of(E e1, E e2, E e3, E e4)217     public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4) {
218         EnumSet<E> set = of(e1, e2, e3);
219         set.add(e4);
220         return set;
221     }
222 
223     /**
224      * Creates a new enum set, containing only the specified elements. There are
225      * six overloadings of the method. They accept from one to five elements
226      * respectively. The sixth one receives an arbitrary number of elements, and
227      * runs slower than those that only receive a fixed number of elements.
228      *
229      * @param e1
230      *            the initially contained element.
231      * @param e2
232      *            another initially contained element.
233      * @param e3
234      *            another initially contained element.
235      * @param e4
236      *            another initially contained element.
237      * @param e5
238      *            another initially contained element.
239      * @return an enum set containing the specified elements.
240      * @throws NullPointerException
241      *             if any of the specified elements is {@code null}.
242      */
of(E e1, E e2, E e3, E e4, E e5)243     public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4, E e5) {
244         EnumSet<E> set = of(e1, e2, e3, e4);
245         set.add(e5);
246         return set;
247     }
248 
249     /**
250      * Creates a new enum set, containing only the specified elements. It can
251      * receive an arbitrary number of elements, and runs slower than those only
252      * receiving a fixed number of elements.
253      *
254      * @param start
255      *            the first initially contained element.
256      * @param others
257      *            the other initially contained elements.
258      * @return an enum set containing the specified elements.
259      * @throws NullPointerException
260      *             if any of the specified elements is {@code null}.
261      */
of(E start, E... others)262     public static <E extends Enum<E>> EnumSet<E> of(E start, E... others) {
263         EnumSet<E> set = of(start);
264         for (E e : others) {
265             set.add(e);
266         }
267         return set;
268     }
269 
270     /**
271      * Creates an enum set containing all the elements within the range defined
272      * by {@code start} and {@code end} (inclusive). All the elements must be in
273      * order.
274      *
275      * @param start
276      *            the element used to define the beginning of the range.
277      * @param end
278      *            the element used to define the end of the range.
279      * @return an enum set with elements in the range from start to end.
280      * @throws NullPointerException
281      *             if any one of {@code start} or {@code end} is {@code null}.
282      * @throws IllegalArgumentException
283      *             if {@code start} is behind {@code end}.
284      */
range(E start, E end)285     public static <E extends Enum<E>> EnumSet<E> range(E start, E end) {
286         if (start.compareTo(end) > 0) {
287             throw new IllegalArgumentException();
288         }
289         EnumSet<E> set = EnumSet.noneOf(start.getDeclaringClass());
290         set.setRange(start, end);
291         return set;
292     }
293 
setRange(E start, E end)294     abstract void setRange(E start, E end);
295 
296     /**
297      * Creates a new enum set with the same elements as those contained in this
298      * enum set.
299      *
300      * @return a new enum set with the same elements as those contained in this
301      *         enum set.
302      */
303     @SuppressWarnings("unchecked")
304     @Override
clone()305     public EnumSet<E> clone() {
306         try {
307             return (EnumSet<E>) super.clone();
308         } catch (CloneNotSupportedException e) {
309             throw new AssertionError(e);
310         }
311     }
312 
isValidType(Class<?> cls)313     boolean isValidType(Class<?> cls) {
314         return cls == elementClass || cls.getSuperclass() == elementClass;
315     }
316 
317     private static class SerializationProxy<E extends Enum<E>> implements
318             Serializable {
319 
320         private static final long serialVersionUID = 362491234563181265L;
321 
322         private Class<E> elementType;
323 
324         private E[] elements;
325 
readResolve()326         private Object readResolve() {
327             EnumSet<E> set = EnumSet.noneOf(elementType);
328             for (E e : elements) {
329                 set.add(e);
330             }
331             return set;
332         }
333     }
334 
335     @SuppressWarnings("unchecked")
writeReplace()336     Object writeReplace() {
337         SerializationProxy proxy = new SerializationProxy();
338         proxy.elements = toArray(new Enum[0]);
339         proxy.elementType = elementClass;
340         return proxy;
341     }
342 }
343