1. /*
  2. * @(#)RegularEnumSet.java 1.6 04/05/28
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.util;
  8. /**
  9. * Private implementation class for EnumSet, for "regular sized" enum types
  10. * (i.e., those with 64 or fewer enum constants).
  11. *
  12. * @author Josh Bloch
  13. * @since 1.5
  14. * @serial exclude
  15. */
  16. class RegularEnumSet<E extends Enum<E>> extends EnumSet<E> {
  17. /**
  18. * Bit vector representation of this set. The 2^k bit indicates the
  19. * presence of universe[k] in this set.
  20. */
  21. private long elements = 0L;
  22. RegularEnumSet(Class<E>elementType, Enum[] universe) {
  23. super(elementType, universe);
  24. }
  25. void addRange(E from, E to) {
  26. elements = (-1L >>> (from.ordinal() - to.ordinal() - 1)) << from.ordinal();
  27. }
  28. void addAll() {
  29. if (universe.length != 0)
  30. elements = -1L >>> -universe.length;
  31. }
  32. void complement() {
  33. if (universe.length != 0) {
  34. elements = ~elements;
  35. elements &= -1L >>> -universe.length; // Mask unused bits
  36. }
  37. }
  38. /**
  39. * Returns an iterator over the elements contained in this set. The
  40. * iterator traverses the elements in their <i>natural order</i> (which is
  41. * the order in which the enum constants are declared). The returned
  42. * Iterator is a "snapshot" iterator that will never throw {@link
  43. * ConcurrentModificationException}; the elements are traversed as they
  44. * existed when this call was invoked.
  45. *
  46. * @return an iterator over the elements contained in this set
  47. */
  48. public Iterator<E> iterator() {
  49. return new EnumSetIterator<E>();
  50. }
  51. private class EnumSetIterator<E extends Enum<E>> implements Iterator<E> {
  52. /**
  53. * A bit vector representing the elements in the set not yet
  54. * returned by this iterator.
  55. */
  56. long unseen;
  57. /**
  58. * The bit representing the last element returned by this iterator
  59. * but not removed, or zero if no such element exists.
  60. */
  61. long lastReturned = 0;
  62. EnumSetIterator() {
  63. unseen = elements;
  64. }
  65. public boolean hasNext() {
  66. return unseen != 0;
  67. }
  68. public E next() {
  69. if (unseen == 0)
  70. throw new NoSuchElementException();
  71. lastReturned = unseen & -unseen;
  72. unseen -= lastReturned;
  73. return (E) universe[Long.numberOfTrailingZeros(lastReturned)];
  74. }
  75. public void remove() {
  76. if (lastReturned == 0)
  77. throw new IllegalStateException();
  78. elements -= lastReturned;
  79. lastReturned = 0;
  80. }
  81. }
  82. /**
  83. * Returns the number of elements in this set.
  84. *
  85. * @return the number of elements in this set
  86. */
  87. public int size() {
  88. return Long.bitCount(elements);
  89. }
  90. /**
  91. * Returns <tt>true</tt> if this set contains no elements.
  92. *
  93. * @return <tt>true</tt> if this set contains no elements
  94. */
  95. public boolean isEmpty() {
  96. return elements == 0;
  97. }
  98. /**
  99. * Returns <tt>true</tt> if this set contains the specified element.
  100. *
  101. * @param e element to be checked for containment in this collection
  102. * @return <tt>true</tt> if this set contains the specified element
  103. */
  104. public boolean contains(Object e) {
  105. if (e == null)
  106. return false;
  107. Class eClass = e.getClass();
  108. if (eClass != elementType && eClass.getSuperclass() != elementType)
  109. return false;
  110. return (elements & (1L << ((Enum)e).ordinal())) != 0;
  111. }
  112. // Modification Operations
  113. /**
  114. * Adds the specified element to this set if it is not already present.
  115. *
  116. * @param e element to be added to this set
  117. * @return <tt>true</tt> if the set changed as a result of the call
  118. *
  119. * @throws NullPointerException if <tt>e</tt> is null
  120. */
  121. public boolean add(E e) {
  122. typeCheck(e);
  123. long oldElements = elements;
  124. elements |= (1L << ((Enum)e).ordinal());
  125. return elements != oldElements;
  126. }
  127. /**
  128. * Removes the specified element from this set if it is present.
  129. *
  130. * @param e element to be removed from this set, if present
  131. * @return <tt>true</tt> if the set contained the specified element
  132. */
  133. public boolean remove(Object e) {
  134. if (e == null)
  135. return false;
  136. Class eClass = e.getClass();
  137. if (eClass != elementType && eClass.getSuperclass() != elementType)
  138. return false;
  139. long oldElements = elements;
  140. elements &= ~(1L << ((Enum)e).ordinal());
  141. return elements != oldElements;
  142. }
  143. // Bulk Operations
  144. /**
  145. * Returns <tt>true</tt> if this set contains all of the elements
  146. * in the specified collection.
  147. *
  148. * @param c collection to be checked for containment in this set
  149. * @return <tt>true</tt> if this set contains all of the elements
  150. * in the specified collection
  151. * @throws NullPointerException if the specified collection is null
  152. */
  153. public boolean containsAll(Collection<?> c) {
  154. if (!(c instanceof RegularEnumSet))
  155. return super.containsAll(c);
  156. RegularEnumSet es = (RegularEnumSet)c;
  157. if (es.elementType != elementType)
  158. return es.isEmpty();
  159. return (es.elements & ~elements) == 0;
  160. }
  161. /**
  162. * Adds all of the elements in the specified collection to this set.
  163. *
  164. * @param c collection whose elements are to be added to this set
  165. * @return <tt>true</tt> if this set changed as a result of the call
  166. * @throws NullPointerException if the specified collection or any
  167. * of its elements are null
  168. */
  169. public boolean addAll(Collection<? extends E> c) {
  170. if (!(c instanceof RegularEnumSet))
  171. return super.addAll(c);
  172. RegularEnumSet es = (RegularEnumSet)c;
  173. if (es.elementType != elementType) {
  174. if (es.isEmpty())
  175. return false;
  176. else
  177. throw new ClassCastException(
  178. es.elementType + " != " + elementType);
  179. }
  180. long oldElements = elements;
  181. elements |= es.elements;
  182. return elements != oldElements;
  183. }
  184. /**
  185. * Removes from this set all of its elements that are contained in
  186. * the specified collection.
  187. *
  188. * @param c elements to be removed from this set
  189. * @return <tt>true</tt> if this set changed as a result of the call
  190. * @throws NullPointerException if the specified collection is null
  191. */
  192. public boolean removeAll(Collection<?> c) {
  193. if (!(c instanceof RegularEnumSet))
  194. return super.removeAll(c);
  195. RegularEnumSet es = (RegularEnumSet)c;
  196. if (es.elementType != elementType)
  197. return false;
  198. long oldElements = elements;
  199. elements &= ~es.elements;
  200. return elements != oldElements;
  201. }
  202. /**
  203. * Retains only the elements in this set that are contained in the
  204. * specified collection.
  205. *
  206. * @param c elements to be retained in this set
  207. * @return <tt>true</tt> if this set changed as a result of the call
  208. * @throws NullPointerException if the specified collection is null
  209. */
  210. public boolean retainAll(Collection<?> c) {
  211. if (!(c instanceof RegularEnumSet))
  212. return super.retainAll(c);
  213. RegularEnumSet es = (RegularEnumSet)c;
  214. if (es.elementType != elementType) {
  215. elements = 0;
  216. return true;
  217. }
  218. long oldElements = elements;
  219. elements &= es.elements;
  220. return elements != oldElements;
  221. }
  222. /**
  223. * Removes all of the elements from this set.
  224. */
  225. public void clear() {
  226. elements = 0;
  227. }
  228. /**
  229. * Compares the specified object with this set for equality. Returns
  230. * <tt>true</tt> if the given object is also a set, the two sets have
  231. * the same size, and every member of the given set is contained in
  232. * this set.
  233. *
  234. * @param e object to be compared for equality with this set
  235. * @return <tt>true</tt> if the specified object is equal to this set
  236. */
  237. public boolean equals(Object o) {
  238. if (!(o instanceof RegularEnumSet))
  239. return super.equals(o);
  240. RegularEnumSet es = (RegularEnumSet)o;
  241. if (es.elementType != elementType)
  242. return elements == 0 && es.elements == 0;
  243. return es.elements == elements;
  244. }
  245. }