001: /* Licensed to the Apache Software Foundation (ASF) under one or more
002: * contributor license agreements. See the NOTICE file distributed with
003: * this work for additional information regarding copyright ownership.
004: * The ASF licenses this file to You under the Apache License, Version 2.0
005: * (the "License"); you may not use this file except in compliance with
006: * the License. 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 java.util;
018:
019: /**
020: * This is a concrete subclass of EnumSet designed specifically for enum type
021: * with less than or equal to 64 elements.
022: *
023: */
024: @SuppressWarnings("serial")
025: final class MiniEnumSet<E extends Enum<E>> extends EnumSet<E> {
026: private static final int MAX_ELEMENTS = 64;
027:
028: private int size;
029:
030: private final E[] enums;
031:
032: private long bits;
033:
034: MiniEnumSet(Class<E> elementType) {
035: super (elementType);
036: enums = elementType.getEnumConstants();
037: }
038:
039: private class MiniEnumSetIterator implements Iterator<E> {
040:
041: private long unProcessedBits;
042:
043: /*
044: * Mask for current element.
045: */
046: private long currentElementMask;
047:
048: private boolean canProcess = true;
049:
050: private MiniEnumSetIterator() {
051: unProcessedBits = bits;
052: if (0 == unProcessedBits) {
053: canProcess = false;
054: }
055: }
056:
057: public boolean hasNext() {
058: return canProcess;
059: }
060:
061: public E next() {
062: if (!canProcess) {
063: throw new NoSuchElementException();
064: }
065: currentElementMask = unProcessedBits & (-unProcessedBits);
066: unProcessedBits -= currentElementMask;
067: if (0 == unProcessedBits) {
068: canProcess = false;
069: }
070: return enums[Long.numberOfTrailingZeros(currentElementMask)];
071: }
072:
073: public void remove() {
074: if (currentElementMask == 0) {
075: throw new IllegalStateException();
076: }
077: bits &= ~currentElementMask;
078: size = Long.bitCount(bits);
079: currentElementMask = 0;
080: }
081: }
082:
083: @Override
084: public Iterator<E> iterator() {
085: return new MiniEnumSetIterator();
086: }
087:
088: @Override
089: public int size() {
090: return size;
091: }
092:
093: @Override
094: public void clear() {
095: bits = 0;
096: size = 0;
097: }
098:
099: @Override
100: public boolean add(E element) {
101: if (!isValidType(element.getDeclaringClass())) {
102: throw new ClassCastException();
103: }
104: long mask = 1l << element.ordinal();
105: if ((bits & mask) == mask) {
106: return false;
107: }
108: bits |= mask;
109:
110: size++;
111: return true;
112: }
113:
114: @Override
115: public boolean addAll(Collection<? extends E> collection) {
116: if (0 == collection.size()) {
117: return false;
118: }
119: if (collection instanceof EnumSet) {
120: EnumSet<?> set = (EnumSet) collection;
121: if (!isValidType(set.elementClass)) {
122: throw new ClassCastException();
123: }
124: MiniEnumSet<?> miniSet = (MiniEnumSet<?>) set;
125: long oldBits = bits;
126: bits |= miniSet.bits;
127: size = Long.bitCount(bits);
128: return (oldBits != bits);
129: }
130: return super .addAll(collection);
131: }
132:
133: @Override
134: public boolean contains(Object object) {
135: if (null == object) {
136: return false;
137: }
138: if (!isValidType(object.getClass())) {
139: return false;
140: }
141: Enum<?> element = (Enum<?>) object;
142: int ordinal = element.ordinal();
143: return (bits & (1l << ordinal)) != 0;
144: }
145:
146: @Override
147: public boolean containsAll(Collection<?> collection) {
148: if (collection.size() == 0) {
149: return true;
150: }
151: if (collection instanceof MiniEnumSet) {
152: MiniEnumSet<?> set = (MiniEnumSet<?>) collection;
153: return isValidType(set.elementClass)
154: && ((bits & set.bits) == set.bits);
155: }
156: return !(collection instanceof EnumSet)
157: && super .containsAll(collection);
158: }
159:
160: @Override
161: public boolean removeAll(Collection<?> collection) {
162: if (0 == collection.size()) {
163: return false;
164: }
165: if (collection instanceof EnumSet) {
166: EnumSet<E> set = (EnumSet<E>) collection;
167: boolean removeSuccessful = false;
168: if (isValidType(set.elementClass)) {
169: long mask = bits & ((MiniEnumSet<E>) set).bits;
170: if (mask != 0) {
171: bits -= mask;
172: size = Long.bitCount(bits);
173: removeSuccessful = true;
174: }
175: }
176: return removeSuccessful;
177: }
178: return super .removeAll(collection);
179: }
180:
181: @Override
182: public boolean retainAll(Collection<?> collection) {
183: if (collection instanceof EnumSet) {
184: EnumSet<E> set = (EnumSet<E>) collection;
185: if (!isValidType(set.elementClass)) {
186: clear();
187: return true;
188: }
189: boolean retainSuccessful = false;
190: long oldBits = bits;
191: bits &= ((MiniEnumSet<E>) set).bits;
192: if (oldBits != bits) {
193: size = Long.bitCount(bits);
194: retainSuccessful = true;
195: }
196: return retainSuccessful;
197: }
198: return super .retainAll(collection);
199: }
200:
201: @Override
202: public boolean remove(Object object) {
203: if (!contains(object)) {
204: return false;
205: }
206: Enum<?> element = (Enum<?>) object;
207: int ordinal = element.ordinal();
208: bits -= (1l << ordinal);
209: size--;
210: return true;
211: }
212:
213: @Override
214: public boolean equals(Object object) {
215: if (!(object instanceof EnumSet)) {
216: return super .equals(object);
217: }
218: EnumSet<?> set = (EnumSet<?>) object;
219: if (!isValidType(set.elementClass)) {
220: return size == 0 && set.size() == 0;
221: }
222: return bits == ((MiniEnumSet<?>) set).bits;
223: }
224:
225: @Override
226: void complement() {
227: if (0 != enums.length) {
228: bits = ~bits;
229: bits &= (-1l >>> (MAX_ELEMENTS - enums.length));
230: size = enums.length - size;
231: }
232: }
233:
234: @Override
235: void setRange(E start, E end) {
236: int length = end.ordinal() - start.ordinal() + 1;
237: long range = (-1l >>> (MAX_ELEMENTS - length)) << start
238: .ordinal();
239: bits |= range;
240: size = Long.bitCount(bits);
241: }
242: }
|