001 /*
002 * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package java.util;
027
028 /**
029 * Private implementation class for EnumSet, for "regular sized" enum types
030 * (i.e., those with 64 or fewer enum constants).
031 *
032 * @author Josh Bloch
033 * @since 1.5
034 * @serial exclude
035 */
036 class RegularEnumSet<E extends Enum<E>> extends EnumSet<E> {
037 /**
038 * Bit vector representation of this set. The 2^k bit indicates the
039 * presence of universe[k] in this set.
040 */
041 private long elements = 0L;
042
043 RegularEnumSet(Class<E> elementType, Enum[] universe) {
044 super (elementType, universe);
045 }
046
047 void addRange(E from, E to) {
048 elements = (-1L >>> (from.ordinal() - to.ordinal() - 1)) << from
049 .ordinal();
050 }
051
052 void addAll() {
053 if (universe.length != 0)
054 elements = -1L >>> -universe.length;
055 }
056
057 void complement() {
058 if (universe.length != 0) {
059 elements = ~elements;
060 elements &= -1L >>> -universe.length; // Mask unused bits
061 }
062 }
063
064 /**
065 * Returns an iterator over the elements contained in this set. The
066 * iterator traverses the elements in their <i>natural order</i> (which is
067 * the order in which the enum constants are declared). The returned
068 * Iterator is a "snapshot" iterator that will never throw {@link
069 * ConcurrentModificationException}; the elements are traversed as they
070 * existed when this call was invoked.
071 *
072 * @return an iterator over the elements contained in this set
073 */
074 public Iterator<E> iterator() {
075 return new EnumSetIterator<E>();
076 }
077
078 private class EnumSetIterator<E extends Enum<E>> implements
079 Iterator<E> {
080 /**
081 * A bit vector representing the elements in the set not yet
082 * returned by this iterator.
083 */
084 long unseen;
085
086 /**
087 * The bit representing the last element returned by this iterator
088 * but not removed, or zero if no such element exists.
089 */
090 long lastReturned = 0;
091
092 EnumSetIterator() {
093 unseen = elements;
094 }
095
096 public boolean hasNext() {
097 return unseen != 0;
098 }
099
100 public E next() {
101 if (unseen == 0)
102 throw new NoSuchElementException();
103 lastReturned = unseen & -unseen;
104 unseen -= lastReturned;
105 return (E) universe[Long
106 .numberOfTrailingZeros(lastReturned)];
107 }
108
109 public void remove() {
110 if (lastReturned == 0)
111 throw new IllegalStateException();
112 elements -= lastReturned;
113 lastReturned = 0;
114 }
115 }
116
117 /**
118 * Returns the number of elements in this set.
119 *
120 * @return the number of elements in this set
121 */
122 public int size() {
123 return Long.bitCount(elements);
124 }
125
126 /**
127 * Returns <tt>true</tt> if this set contains no elements.
128 *
129 * @return <tt>true</tt> if this set contains no elements
130 */
131 public boolean isEmpty() {
132 return elements == 0;
133 }
134
135 /**
136 * Returns <tt>true</tt> if this set contains the specified element.
137 *
138 * @param e element to be checked for containment in this collection
139 * @return <tt>true</tt> if this set contains the specified element
140 */
141 public boolean contains(Object e) {
142 if (e == null)
143 return false;
144 Class eClass = e.getClass();
145 if (eClass != elementType
146 && eClass.getSuperclass() != elementType)
147 return false;
148
149 return (elements & (1L << ((Enum) e).ordinal())) != 0;
150 }
151
152 // Modification Operations
153
154 /**
155 * Adds the specified element to this set if it is not already present.
156 *
157 * @param e element to be added to this set
158 * @return <tt>true</tt> if the set changed as a result of the call
159 *
160 * @throws NullPointerException if <tt>e</tt> is null
161 */
162 public boolean add(E e) {
163 typeCheck(e);
164
165 long oldElements = elements;
166 elements |= (1L << ((Enum) e).ordinal());
167 return elements != oldElements;
168 }
169
170 /**
171 * Removes the specified element from this set if it is present.
172 *
173 * @param e element to be removed from this set, if present
174 * @return <tt>true</tt> if the set contained the specified element
175 */
176 public boolean remove(Object e) {
177 if (e == null)
178 return false;
179 Class eClass = e.getClass();
180 if (eClass != elementType
181 && eClass.getSuperclass() != elementType)
182 return false;
183
184 long oldElements = elements;
185 elements &= ~(1L << ((Enum) e).ordinal());
186 return elements != oldElements;
187 }
188
189 // Bulk Operations
190
191 /**
192 * Returns <tt>true</tt> if this set contains all of the elements
193 * in the specified collection.
194 *
195 * @param c collection to be checked for containment in this set
196 * @return <tt>true</tt> if this set contains all of the elements
197 * in the specified collection
198 * @throws NullPointerException if the specified collection is null
199 */
200 public boolean containsAll(Collection<?> c) {
201 if (!(c instanceof RegularEnumSet))
202 return super .containsAll(c);
203
204 RegularEnumSet es = (RegularEnumSet) c;
205 if (es.elementType != elementType)
206 return es.isEmpty();
207
208 return (es.elements & ~elements) == 0;
209 }
210
211 /**
212 * Adds all of the elements in the specified collection to this set.
213 *
214 * @param c collection whose elements are to be added to this set
215 * @return <tt>true</tt> if this set changed as a result of the call
216 * @throws NullPointerException if the specified collection or any
217 * of its elements are null
218 */
219 public boolean addAll(Collection<? extends E> c) {
220 if (!(c instanceof RegularEnumSet))
221 return super .addAll(c);
222
223 RegularEnumSet es = (RegularEnumSet) c;
224 if (es.elementType != elementType) {
225 if (es.isEmpty())
226 return false;
227 else
228 throw new ClassCastException(es.elementType + " != "
229 + elementType);
230 }
231
232 long oldElements = elements;
233 elements |= es.elements;
234 return elements != oldElements;
235 }
236
237 /**
238 * Removes from this set all of its elements that are contained in
239 * the specified collection.
240 *
241 * @param c elements to be removed from this set
242 * @return <tt>true</tt> if this set changed as a result of the call
243 * @throws NullPointerException if the specified collection is null
244 */
245 public boolean removeAll(Collection<?> c) {
246 if (!(c instanceof RegularEnumSet))
247 return super .removeAll(c);
248
249 RegularEnumSet es = (RegularEnumSet) c;
250 if (es.elementType != elementType)
251 return false;
252
253 long oldElements = elements;
254 elements &= ~es.elements;
255 return elements != oldElements;
256 }
257
258 /**
259 * Retains only the elements in this set that are contained in the
260 * specified collection.
261 *
262 * @param c elements to be retained in this set
263 * @return <tt>true</tt> if this set changed as a result of the call
264 * @throws NullPointerException if the specified collection is null
265 */
266 public boolean retainAll(Collection<?> c) {
267 if (!(c instanceof RegularEnumSet))
268 return super .retainAll(c);
269
270 RegularEnumSet<?> es = (RegularEnumSet<?>) c;
271 if (es.elementType != elementType) {
272 boolean changed = (elements != 0);
273 elements = 0;
274 return changed;
275 }
276
277 long oldElements = elements;
278 elements &= es.elements;
279 return elements != oldElements;
280 }
281
282 /**
283 * Removes all of the elements from this set.
284 */
285 public void clear() {
286 elements = 0;
287 }
288
289 /**
290 * Compares the specified object with this set for equality. Returns
291 * <tt>true</tt> if the given object is also a set, the two sets have
292 * the same size, and every member of the given set is contained in
293 * this set.
294 *
295 * @param e object to be compared for equality with this set
296 * @return <tt>true</tt> if the specified object is equal to this set
297 */
298 public boolean equals(Object o) {
299 if (!(o instanceof RegularEnumSet))
300 return super .equals(o);
301
302 RegularEnumSet es = (RegularEnumSet) o;
303 if (es.elementType != elementType)
304 return elements == 0 && es.elements == 0;
305 return es.elements == elements;
306 }
307 }
|