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

    1   /*
    2    * Copyright (c) 2003, 2011, Oracle and/or its affiliates. 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.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package java.util;
   27   
   28   import sun.misc.SharedSecrets;
   29   
   30   /**
   31    * A specialized {@link Set} implementation for use with enum types.  All of
   32    * the elements in an enum set must come from a single enum type that is
   33    * specified, explicitly or implicitly, when the set is created.  Enum sets
   34    * are represented internally as bit vectors.  This representation is
   35    * extremely compact and efficient. The space and time performance of this
   36    * class should be good enough to allow its use as a high-quality, typesafe
   37    * alternative to traditional <tt>int</tt>-based "bit flags."  Even bulk
   38    * operations (such as <tt>containsAll</tt> and <tt>retainAll</tt>) should
   39    * run very quickly if their argument is also an enum set.
   40    *
   41    * <p>The iterator returned by the <tt>iterator</tt> method traverses the
   42    * elements in their <i>natural order</i> (the order in which the enum
   43    * constants are declared).  The returned iterator is <i>weakly
   44    * consistent</i>: it will never throw {@link ConcurrentModificationException}
   45    * and it may or may not show the effects of any modifications to the set that
   46    * occur while the iteration is in progress.
   47    *
   48    * <p>Null elements are not permitted.  Attempts to insert a null element
   49    * will throw {@link NullPointerException}.  Attempts to test for the
   50    * presence of a null element or to remove one will, however, function
   51    * properly.
   52    *
   53    * <P>Like most collection implementations, <tt>EnumSet</tt> is not
   54    * synchronized.  If multiple threads access an enum set concurrently, and at
   55    * least one of the threads modifies the set, it should be synchronized
   56    * externally.  This is typically accomplished by synchronizing on some
   57    * object that naturally encapsulates the enum set.  If no such object exists,
   58    * the set should be "wrapped" using the {@link Collections#synchronizedSet}
   59    * method.  This is best done at creation time, to prevent accidental
   60    * unsynchronized access:
   61    *
   62    * <pre>
   63    * Set&lt;MyEnum&gt; s = Collections.synchronizedSet(EnumSet.noneOf(MyEnum.class));
   64    * </pre>
   65    *
   66    * <p>Implementation note: All basic operations execute in constant time.
   67    * They are likely (though not guaranteed) to be much faster than their
   68    * {@link HashSet} counterparts.  Even bulk operations execute in
   69    * constant time if their argument is also an enum set.
   70    *
   71    * <p>This class is a member of the
   72    * <a href="{@docRoot}/../technotes/guides/collections/index.html">
   73    * Java Collections Framework</a>.
   74    *
   75    * @author Josh Bloch
   76    * @since 1.5
   77    * @see EnumMap
   78    * @serial exclude
   79    */
   80   public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E>
   81       implements Cloneable, java.io.Serializable
   82   {
   83       /**
   84        * The class of all the elements of this set.
   85        */
   86       final Class<E> elementType;
   87   
   88       /**
   89        * All of the values comprising T.  (Cached for performance.)
   90        */
   91       final Enum[] universe;
   92   
   93       private static Enum[] ZERO_LENGTH_ENUM_ARRAY = new Enum[0];
   94   
   95       EnumSet(Class<E>elementType, Enum[] universe) {
   96           this.elementType = elementType;
   97           this.universe    = universe;
   98       }
   99   
  100       /**
  101        * Creates an empty enum set with the specified element type.
  102        *
  103        * @param elementType the class object of the element type for this enum
  104        *     set
  105        * @throws NullPointerException if <tt>elementType</tt> is null
  106        */
  107       public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
  108           Enum[] universe = getUniverse(elementType);
  109           if (universe == null)
  110               throw new ClassCastException(elementType + " not an enum");
  111   
  112           if (universe.length <= 64)
  113               return new RegularEnumSet<>(elementType, universe);
  114           else
  115               return new JumboEnumSet<>(elementType, universe);
  116       }
  117   
  118       /**
  119        * Creates an enum set containing all of the elements in the specified
  120        * element type.
  121        *
  122        * @param elementType the class object of the element type for this enum
  123        *     set
  124        * @throws NullPointerException if <tt>elementType</tt> is null
  125        */
  126       public static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType) {
  127           EnumSet<E> result = noneOf(elementType);
  128           result.addAll();
  129           return result;
  130       }
  131   
  132       /**
  133        * Adds all of the elements from the appropriate enum type to this enum
  134        * set, which is empty prior to the call.
  135        */
  136       abstract void addAll();
  137   
  138       /**
  139        * Creates an enum set with the same element type as the specified enum
  140        * set, initially containing the same elements (if any).
  141        *
  142        * @param s the enum set from which to initialize this enum set
  143        * @throws NullPointerException if <tt>s</tt> is null
  144        */
  145       public static <E extends Enum<E>> EnumSet<E> copyOf(EnumSet<E> s) {
  146           return s.clone();
  147       }
  148   
  149       /**
  150        * Creates an enum set initialized from the specified collection.  If
  151        * the specified collection is an <tt>EnumSet</tt> instance, this static
  152        * factory method behaves identically to {@link #copyOf(EnumSet)}.
  153        * Otherwise, the specified collection must contain at least one element
  154        * (in order to determine the new enum set's element type).
  155        *
  156        * @param c the collection from which to initialize this enum set
  157        * @throws IllegalArgumentException if <tt>c</tt> is not an
  158        *     <tt>EnumSet</tt> instance and contains no elements
  159        * @throws NullPointerException if <tt>c</tt> is null
  160        */
  161       public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c) {
  162           if (c instanceof EnumSet) {
  163               return ((EnumSet<E>)c).clone();
  164           } else {
  165               if (c.isEmpty())
  166                   throw new IllegalArgumentException("Collection is empty");
  167               Iterator<E> i = c.iterator();
  168               E first = i.next();
  169               EnumSet<E> result = EnumSet.of(first);
  170               while (i.hasNext())
  171                   result.add(i.next());
  172               return result;
  173           }
  174       }
  175   
  176       /**
  177        * Creates an enum set with the same element type as the specified enum
  178        * set, initially containing all the elements of this type that are
  179        * <i>not</i> contained in the specified set.
  180        *
  181        * @param s the enum set from whose complement to initialize this enum set
  182        * @throws NullPointerException if <tt>s</tt> is null
  183        */
  184       public static <E extends Enum<E>> EnumSet<E> complementOf(EnumSet<E> s) {
  185           EnumSet<E> result = copyOf(s);
  186           result.complement();
  187           return result;
  188       }
  189   
  190       /**
  191        * Creates an enum set initially containing the specified element.
  192        *
  193        * Overloadings of this method exist to initialize an enum set with
  194        * one through five elements.  A sixth overloading is provided that
  195        * uses the varargs feature.  This overloading may be used to create
  196        * an enum set initially containing an arbitrary number of elements, but
  197        * is likely to run slower than the overloadings that do not use varargs.
  198        *
  199        * @param e the element that this set is to contain initially
  200        * @throws NullPointerException if <tt>e</tt> is null
  201        * @return an enum set initially containing the specified element
  202        */
  203       public static <E extends Enum<E>> EnumSet<E> of(E e) {
  204           EnumSet<E> result = noneOf(e.getDeclaringClass());
  205           result.add(e);
  206           return result;
  207       }
  208   
  209       /**
  210        * Creates an enum set initially containing the specified elements.
  211        *
  212        * Overloadings of this method exist to initialize an enum set with
  213        * one through five elements.  A sixth overloading is provided that
  214        * uses the varargs feature.  This overloading may be used to create
  215        * an enum set initially containing an arbitrary number of elements, but
  216        * is likely to run slower than the overloadings that do not use varargs.
  217        *
  218        * @param e1 an element that this set is to contain initially
  219        * @param e2 another element that this set is to contain initially
  220        * @throws NullPointerException if any parameters are null
  221        * @return an enum set initially containing the specified elements
  222        */
  223       public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2) {
  224           EnumSet<E> result = noneOf(e1.getDeclaringClass());
  225           result.add(e1);
  226           result.add(e2);
  227           return result;
  228       }
  229   
  230       /**
  231        * Creates an enum set initially containing the specified elements.
  232        *
  233        * Overloadings of this method exist to initialize an enum set with
  234        * one through five elements.  A sixth overloading is provided that
  235        * uses the varargs feature.  This overloading may be used to create
  236        * an enum set initially containing an arbitrary number of elements, but
  237        * is likely to run slower than the overloadings that do not use varargs.
  238        *
  239        * @param e1 an element that this set is to contain initially
  240        * @param e2 another element that this set is to contain initially
  241        * @param e3 another element that this set is to contain initially
  242        * @throws NullPointerException if any parameters are null
  243        * @return an enum set initially containing the specified elements
  244        */
  245       public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3) {
  246           EnumSet<E> result = noneOf(e1.getDeclaringClass());
  247           result.add(e1);
  248           result.add(e2);
  249           result.add(e3);
  250           return result;
  251       }
  252   
  253       /**
  254        * Creates an enum set initially containing the specified elements.
  255        *
  256        * Overloadings of this method exist to initialize an enum set with
  257        * one through five elements.  A sixth overloading is provided that
  258        * uses the varargs feature.  This overloading may be used to create
  259        * an enum set initially containing an arbitrary number of elements, but
  260        * is likely to run slower than the overloadings that do not use varargs.
  261        *
  262        * @param e1 an element that this set is to contain initially
  263        * @param e2 another element that this set is to contain initially
  264        * @param e3 another element that this set is to contain initially
  265        * @param e4 another element that this set is to contain initially
  266        * @throws NullPointerException if any parameters are null
  267        * @return an enum set initially containing the specified elements
  268        */
  269       public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4) {
  270           EnumSet<E> result = noneOf(e1.getDeclaringClass());
  271           result.add(e1);
  272           result.add(e2);
  273           result.add(e3);
  274           result.add(e4);
  275           return result;
  276       }
  277   
  278       /**
  279        * Creates an enum set initially containing the specified elements.
  280        *
  281        * Overloadings of this method exist to initialize an enum set with
  282        * one through five elements.  A sixth overloading is provided that
  283        * uses the varargs feature.  This overloading may be used to create
  284        * an enum set initially containing an arbitrary number of elements, but
  285        * is likely to run slower than the overloadings that do not use varargs.
  286        *
  287        * @param e1 an element that this set is to contain initially
  288        * @param e2 another element that this set is to contain initially
  289        * @param e3 another element that this set is to contain initially
  290        * @param e4 another element that this set is to contain initially
  291        * @param e5 another element that this set is to contain initially
  292        * @throws NullPointerException if any parameters are null
  293        * @return an enum set initially containing the specified elements
  294        */
  295       public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4,
  296                                                       E e5)
  297       {
  298           EnumSet<E> result = noneOf(e1.getDeclaringClass());
  299           result.add(e1);
  300           result.add(e2);
  301           result.add(e3);
  302           result.add(e4);
  303           result.add(e5);
  304           return result;
  305       }
  306   
  307       /**
  308        * Creates an enum set initially containing the specified elements.
  309        * This factory, whose parameter list uses the varargs feature, may
  310        * be used to create an enum set initially containing an arbitrary
  311        * number of elements, but it is likely to run slower than the overloadings
  312        * that do not use varargs.
  313        *
  314        * @param first an element that the set is to contain initially
  315        * @param rest the remaining elements the set is to contain initially
  316        * @throws NullPointerException if any of the specified elements are null,
  317        *     or if <tt>rest</tt> is null
  318        * @return an enum set initially containing the specified elements
  319        */
  320       @SafeVarargs
  321       public static <E extends Enum<E>> EnumSet<E> of(E first, E... rest) {
  322           EnumSet<E> result = noneOf(first.getDeclaringClass());
  323           result.add(first);
  324           for (E e : rest)
  325               result.add(e);
  326           return result;
  327       }
  328   
  329       /**
  330        * Creates an enum set initially containing all of the elements in the
  331        * range defined by the two specified endpoints.  The returned set will
  332        * contain the endpoints themselves, which may be identical but must not
  333        * be out of order.
  334        *
  335        * @param from the first element in the range
  336        * @param to the last element in the range
  337        * @throws NullPointerException if {@code from} or {@code to} are null
  338        * @throws IllegalArgumentException if {@code from.compareTo(to) > 0}
  339        * @return an enum set initially containing all of the elements in the
  340        *         range defined by the two specified endpoints
  341        */
  342       public static <E extends Enum<E>> EnumSet<E> range(E from, E to) {
  343           if (from.compareTo(to) > 0)
  344               throw new IllegalArgumentException(from + " > " + to);
  345           EnumSet<E> result = noneOf(from.getDeclaringClass());
  346           result.addRange(from, to);
  347           return result;
  348       }
  349   
  350       /**
  351        * Adds the specified range to this enum set, which is empty prior
  352        * to the call.
  353        */
  354       abstract void addRange(E from, E to);
  355   
  356       /**
  357        * Returns a copy of this set.
  358        *
  359        * @return a copy of this set
  360        */
  361       public EnumSet<E> clone() {
  362           try {
  363               return (EnumSet<E>) super.clone();
  364           } catch(CloneNotSupportedException e) {
  365               throw new AssertionError(e);
  366           }
  367       }
  368   
  369       /**
  370        * Complements the contents of this enum set.
  371        */
  372       abstract void complement();
  373   
  374       /**
  375        * Throws an exception if e is not of the correct type for this enum set.
  376        */
  377       final void typeCheck(E e) {
  378           Class eClass = e.getClass();
  379           if (eClass != elementType && eClass.getSuperclass() != elementType)
  380               throw new ClassCastException(eClass + " != " + elementType);
  381       }
  382   
  383       /**
  384        * Returns all of the values comprising E.
  385        * The result is uncloned, cached, and shared by all callers.
  386        */
  387       private static <E extends Enum<E>> E[] getUniverse(Class<E> elementType) {
  388           return SharedSecrets.getJavaLangAccess()
  389                                           .getEnumConstantsShared(elementType);
  390       }
  391   
  392       /**
  393        * This class is used to serialize all EnumSet instances, regardless of
  394        * implementation type.  It captures their "logical contents" and they
  395        * are reconstructed using public static factories.  This is necessary
  396        * to ensure that the existence of a particular implementation type is
  397        * an implementation detail.
  398        *
  399        * @serial include
  400        */
  401       private static class SerializationProxy <E extends Enum<E>>
  402           implements java.io.Serializable
  403       {
  404           /**
  405            * The element type of this enum set.
  406            *
  407            * @serial
  408            */
  409           private final Class<E> elementType;
  410   
  411           /**
  412            * The elements contained in this enum set.
  413            *
  414            * @serial
  415            */
  416           private final Enum[] elements;
  417   
  418           SerializationProxy(EnumSet<E> set) {
  419               elementType = set.elementType;
  420               elements = set.toArray(ZERO_LENGTH_ENUM_ARRAY);
  421           }
  422   
  423           private Object readResolve() {
  424               EnumSet<E> result = EnumSet.noneOf(elementType);
  425               for (Enum e : elements)
  426                   result.add((E)e);
  427               return result;
  428           }
  429   
  430           private static final long serialVersionUID = 362491234563181265L;
  431       }
  432   
  433       Object writeReplace() {
  434           return new SerializationProxy<>(this);
  435       }
  436   
  437       // readObject method for the serialization proxy pattern
  438       // See Effective Java, Second Ed., Item 78.
  439       private void readObject(java.io.ObjectInputStream stream)
  440           throws java.io.InvalidObjectException {
  441           throw new java.io.InvalidObjectException("Proxy required");
  442       }
  443   }

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