Save This Page
Home » openjdk-7 » java » util » [javadoc | source]
    1   /*
    2    * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package java.util;
   27   
   28   /**
   29    * Private implementation class for EnumSet, for "jumbo" enum types
   30    * (i.e., those with more than 64 elements).
   31    *
   32    * @author Josh Bloch
   33    * @since 1.5
   34    * @serial exclude
   35    */
   36   class JumboEnumSet<E extends Enum<E>> extends EnumSet<E> {
   37       /**
   38        * Bit vector representation of this set.  The ith bit of the jth
   39        * element of this array represents the  presence of universe[64*j +i]
   40        * in this set.
   41        */
   42       private long elements[];
   43   
   44       // Redundant - maintained for performance
   45       private int size = 0;
   46   
   47       JumboEnumSet(Class<E>elementType, Enum[] universe) {
   48           super(elementType, universe);
   49           elements = new long[(universe.length + 63) >>> 6];
   50       }
   51   
   52       void addRange(E from, E to) {
   53           int fromIndex = from.ordinal() >>> 6;
   54           int toIndex = to.ordinal() >>> 6;
   55   
   56           if (fromIndex == toIndex) {
   57               elements[fromIndex] = (-1L >>>  (from.ordinal() - to.ordinal() - 1))
   58                               << from.ordinal();
   59           } else {
   60               elements[fromIndex] = (-1L << from.ordinal());
   61               for (int i = fromIndex + 1; i < toIndex; i++)
   62                   elements[i] = -1;
   63               elements[toIndex] = -1L >>> (63 - to.ordinal());
   64           }
   65           size = to.ordinal() - from.ordinal() + 1;
   66       }
   67   
   68       void addAll() {
   69           for (int i = 0; i < elements.length; i++)
   70               elements[i] = -1;
   71           elements[elements.length - 1] >>>= -universe.length;
   72           size = universe.length;
   73       }
   74   
   75       void complement() {
   76           for (int i = 0; i < elements.length; i++)
   77               elements[i] = ~elements[i];
   78           elements[elements.length - 1] &= (-1L >>> -universe.length);
   79           size = universe.length - size;
   80       }
   81   
   82       /**
   83        * Returns an iterator over the elements contained in this set.  The
   84        * iterator traverses the elements in their <i>natural order</i> (which is
   85        * the order in which the enum constants are declared). The returned
   86        * Iterator is a "weakly consistent" iterator that will never throw {@link
   87        * ConcurrentModificationException}.
   88        *
   89        * @return an iterator over the elements contained in this set
   90        */
   91       public Iterator<E> iterator() {
   92           return new EnumSetIterator<E>();
   93       }
   94   
   95       private class EnumSetIterator<E extends Enum<E>> implements Iterator<E> {
   96           /**
   97            * A bit vector representing the elements in the current "word"
   98            * of the set not yet returned by this iterator.
   99            */
  100           long unseen;
  101   
  102           /**
  103            * The index corresponding to unseen in the elements array.
  104            */
  105           int unseenIndex = 0;
  106   
  107           /**
  108            * The bit representing the last element returned by this iterator
  109            * but not removed, or zero if no such element exists.
  110            */
  111           long lastReturned = 0;
  112   
  113           /**
  114            * The index corresponding to lastReturned in the elements array.
  115            */
  116           int lastReturnedIndex = 0;
  117   
  118           EnumSetIterator() {
  119               unseen = elements[0];
  120           }
  121   
  122           public boolean hasNext() {
  123               while (unseen == 0 && unseenIndex < elements.length - 1)
  124                   unseen = elements[++unseenIndex];
  125               return unseen != 0;
  126           }
  127   
  128           public E next() {
  129               if (!hasNext())
  130                   throw new NoSuchElementException();
  131               lastReturned = unseen & -unseen;
  132               lastReturnedIndex = unseenIndex;
  133               unseen -= lastReturned;
  134               return (E) universe[(lastReturnedIndex << 6)
  135                                   + Long.numberOfTrailingZeros(lastReturned)];
  136           }
  137   
  138           public void remove() {
  139               if (lastReturned == 0)
  140                   throw new IllegalStateException();
  141               elements[lastReturnedIndex] -= lastReturned;
  142               size--;
  143               lastReturned = 0;
  144           }
  145       }
  146   
  147       /**
  148        * Returns the number of elements in this set.
  149        *
  150        * @return the number of elements in this set
  151        */
  152       public int size() {
  153           return size;
  154       }
  155   
  156       /**
  157        * Returns <tt>true</tt> if this set contains no elements.
  158        *
  159        * @return <tt>true</tt> if this set contains no elements
  160        */
  161       public boolean isEmpty() {
  162           return size == 0;
  163       }
  164   
  165       /**
  166        * Returns <tt>true</tt> if this set contains the specified element.
  167        *
  168        * @param e element to be checked for containment in this collection
  169        * @return <tt>true</tt> if this set contains the specified element
  170        */
  171       public boolean contains(Object e) {
  172           if (e == null)
  173               return false;
  174           Class eClass = e.getClass();
  175           if (eClass != elementType && eClass.getSuperclass() != elementType)
  176               return false;
  177   
  178           int eOrdinal = ((Enum)e).ordinal();
  179           return (elements[eOrdinal >>> 6] & (1L << eOrdinal)) != 0;
  180       }
  181   
  182       // Modification Operations
  183   
  184       /**
  185        * Adds the specified element to this set if it is not already present.
  186        *
  187        * @param e element to be added to this set
  188        * @return <tt>true</tt> if the set changed as a result of the call
  189        *
  190        * @throws NullPointerException if <tt>e</tt> is null
  191        */
  192       public boolean add(E e) {
  193           typeCheck(e);
  194   
  195           int eOrdinal = e.ordinal();
  196           int eWordNum = eOrdinal >>> 6;
  197   
  198           long oldElements = elements[eWordNum];
  199           elements[eWordNum] |= (1L << eOrdinal);
  200           boolean result = (elements[eWordNum] != oldElements);
  201           if (result)
  202               size++;
  203           return result;
  204       }
  205   
  206       /**
  207        * Removes the specified element from this set if it is present.
  208        *
  209        * @param e element to be removed from this set, if present
  210        * @return <tt>true</tt> if the set contained the specified element
  211        */
  212       public boolean remove(Object e) {
  213           if (e == null)
  214               return false;
  215           Class eClass = e.getClass();
  216           if (eClass != elementType && eClass.getSuperclass() != elementType)
  217               return false;
  218           int eOrdinal = ((Enum)e).ordinal();
  219           int eWordNum = eOrdinal >>> 6;
  220   
  221           long oldElements = elements[eWordNum];
  222           elements[eWordNum] &= ~(1L << eOrdinal);
  223           boolean result = (elements[eWordNum] != oldElements);
  224           if (result)
  225               size--;
  226           return result;
  227       }
  228   
  229       // Bulk Operations
  230   
  231       /**
  232        * Returns <tt>true</tt> if this set contains all of the elements
  233        * in the specified collection.
  234        *
  235        * @param c collection to be checked for containment in this set
  236        * @return <tt>true</tt> if this set contains all of the elements
  237        *        in the specified collection
  238        * @throws NullPointerException if the specified collection is null
  239        */
  240       public boolean containsAll(Collection<?> c) {
  241           if (!(c instanceof JumboEnumSet))
  242               return super.containsAll(c);
  243   
  244           JumboEnumSet es = (JumboEnumSet)c;
  245           if (es.elementType != elementType)
  246               return es.isEmpty();
  247   
  248           for (int i = 0; i < elements.length; i++)
  249               if ((es.elements[i] & ~elements[i]) != 0)
  250                   return false;
  251           return true;
  252       }
  253   
  254       /**
  255        * Adds all of the elements in the specified collection to this set.
  256        *
  257        * @param c collection whose elements are to be added to this set
  258        * @return <tt>true</tt> if this set changed as a result of the call
  259        * @throws NullPointerException if the specified collection or any of
  260        *     its elements are null
  261        */
  262       public boolean addAll(Collection<? extends E> c) {
  263           if (!(c instanceof JumboEnumSet))
  264               return super.addAll(c);
  265   
  266           JumboEnumSet es = (JumboEnumSet)c;
  267           if (es.elementType != elementType) {
  268               if (es.isEmpty())
  269                   return false;
  270               else
  271                   throw new ClassCastException(
  272                       es.elementType + " != " + elementType);
  273           }
  274   
  275           for (int i = 0; i < elements.length; i++)
  276               elements[i] |= es.elements[i];
  277           return recalculateSize();
  278       }
  279   
  280       /**
  281        * Removes from this set all of its elements that are contained in
  282        * the specified collection.
  283        *
  284        * @param c elements to be removed from this set
  285        * @return <tt>true</tt> if this set changed as a result of the call
  286        * @throws NullPointerException if the specified collection is null
  287        */
  288       public boolean removeAll(Collection<?> c) {
  289           if (!(c instanceof JumboEnumSet))
  290               return super.removeAll(c);
  291   
  292           JumboEnumSet es = (JumboEnumSet)c;
  293           if (es.elementType != elementType)
  294               return false;
  295   
  296           for (int i = 0; i < elements.length; i++)
  297               elements[i] &= ~es.elements[i];
  298           return recalculateSize();
  299       }
  300   
  301       /**
  302        * Retains only the elements in this set that are contained in the
  303        * specified collection.
  304        *
  305        * @param c elements to be retained in this set
  306        * @return <tt>true</tt> if this set changed as a result of the call
  307        * @throws NullPointerException if the specified collection is null
  308        */
  309       public boolean retainAll(Collection<?> c) {
  310           if (!(c instanceof JumboEnumSet))
  311               return super.retainAll(c);
  312   
  313           JumboEnumSet<?> es = (JumboEnumSet<?>)c;
  314           if (es.elementType != elementType) {
  315               boolean changed = (size != 0);
  316               clear();
  317               return changed;
  318           }
  319   
  320           for (int i = 0; i < elements.length; i++)
  321               elements[i] &= es.elements[i];
  322           return recalculateSize();
  323       }
  324   
  325       /**
  326        * Removes all of the elements from this set.
  327        */
  328       public void clear() {
  329           Arrays.fill(elements, 0);
  330           size = 0;
  331       }
  332   
  333       /**
  334        * Compares the specified object with this set for equality.  Returns
  335        * <tt>true</tt> if the given object is also a set, the two sets have
  336        * the same size, and every member of the given set is contained in
  337        * this set.
  338        *
  339        * @param e object to be compared for equality with this set
  340        * @return <tt>true</tt> if the specified object is equal to this set
  341        */
  342       public boolean equals(Object o) {
  343           if (!(o instanceof JumboEnumSet))
  344               return super.equals(o);
  345   
  346           JumboEnumSet es = (JumboEnumSet)o;
  347           if (es.elementType != elementType)
  348               return size == 0 && es.size == 0;
  349   
  350           return Arrays.equals(es.elements, elements);
  351       }
  352   
  353       /**
  354        * Recalculates the size of the set.  Returns true if it's changed.
  355        */
  356       private boolean recalculateSize() {
  357           int oldSize = size;
  358           size = 0;
  359           for (long elt : elements)
  360               size += Long.bitCount(elt);
  361   
  362           return size != oldSize;
  363       }
  364   
  365       public EnumSet<E> clone() {
  366           JumboEnumSet<E> result = (JumboEnumSet<E>) super.clone();
  367           result.elements = result.elements.clone();
  368           return result;
  369       }
  370   }

Save This Page
Home » openjdk-7 » java » util » [javadoc | source]