303 lines · 9.6 KB · Java
RawDownload
/* * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.util; /** * Private implementation class for EnumSet, for "regular sized" enum types * (i.e., those with 64 or fewer enum constants). * * @author Josh Bloch * @since 1.5 * @serial exclude */class RegularEnumSet<E extends Enum<E>> extends EnumSet<E> {    private static final long serialVersionUID = 3411599620347842686L;    /**     * Bit vector representation of this set.  The 2^k bit indicates the     * presence of universe[k] in this set.     */    private long elements = 0L;     RegularEnumSet(Class<E>elementType, Enum[] universe) {        super(elementType, universe);    }     void addRange(E from, E to) {        elements = (-1L >>>  (from.ordinal() - to.ordinal() - 1)) << from.ordinal();    }     void addAll() {        if (universe.length != 0)            elements = -1L >>> -universe.length;    }     void complement() {        if (universe.length != 0) {            elements = ~elements;            elements &= -1L >>> -universe.length;  // Mask unused bits        }    }     /**     * Returns an iterator over the elements contained in this set.  The     * iterator traverses the elements in their <i>natural order</i> (which is     * the order in which the enum constants are declared). The returned     * Iterator is a "snapshot" iterator that will never throw {@link     * ConcurrentModificationException}; the elements are traversed as they     * existed when this call was invoked.     *     * @return an iterator over the elements contained in this set     */    public Iterator<E> iterator() {        return new EnumSetIterator<>();    }     private class EnumSetIterator<E extends Enum<E>> implements Iterator<E> {        /**         * A bit vector representing the elements in the set not yet         * returned by this iterator.         */        long unseen;         /**         * The bit representing the last element returned by this iterator         * but not removed, or zero if no such element exists.         */        long lastReturned = 0;         EnumSetIterator() {            unseen = elements;        }         public boolean hasNext() {            return unseen != 0;        }         public E next() {            if (unseen == 0)                throw new NoSuchElementException();            lastReturned = unseen & -unseen;            unseen -= lastReturned;            return (E) universe[Long.numberOfTrailingZeros(lastReturned)];        }         public void remove() {            if (lastReturned == 0)                throw new IllegalStateException();            elements &= ~lastReturned;            lastReturned = 0;        }    }     /**     * Returns the number of elements in this set.     *     * @return the number of elements in this set     */    public int size() {        return Long.bitCount(elements);    }     /**     * Returns <tt>true</tt> if this set contains no elements.     *     * @return <tt>true</tt> if this set contains no elements     */    public boolean isEmpty() {        return elements == 0;    }     /**     * Returns <tt>true</tt> if this set contains the specified element.     *     * @param e element to be checked for containment in this collection     * @return <tt>true</tt> if this set contains the specified element     */    public boolean contains(Object e) {        if (e == null)            return false;        Class eClass = e.getClass();        if (eClass != elementType && eClass.getSuperclass() != elementType)            return false;         return (elements & (1L << ((Enum)e).ordinal())) != 0;    }     // Modification Operations     /**     * Adds the specified element to this set if it is not already present.     *     * @param e element to be added to this set     * @return <tt>true</tt> if the set changed as a result of the call     *     * @throws NullPointerException if <tt>e</tt> is null     */    public boolean add(E e) {        typeCheck(e);         long oldElements = elements;        elements |= (1L << ((Enum)e).ordinal());        return elements != oldElements;    }     /**     * Removes the specified element from this set if it is present.     *     * @param e element to be removed from this set, if present     * @return <tt>true</tt> if the set contained the specified element     */    public boolean remove(Object e) {        if (e == null)            return false;        Class eClass = e.getClass();        if (eClass != elementType && eClass.getSuperclass() != elementType)            return false;         long oldElements = elements;        elements &= ~(1L << ((Enum)e).ordinal());        return elements != oldElements;    }     // Bulk Operations     /**     * Returns <tt>true</tt> if this set contains all of the elements     * in the specified collection.     *     * @param c collection to be checked for containment in this set     * @return <tt>true</tt> if this set contains all of the elements     *        in the specified collection     * @throws NullPointerException if the specified collection is null     */    public boolean containsAll(Collection<?> c) {        if (!(c instanceof RegularEnumSet))            return super.containsAll(c);         RegularEnumSet es = (RegularEnumSet)c;        if (es.elementType != elementType)            return es.isEmpty();         return (es.elements & ~elements) == 0;    }     /**     * Adds all of the elements in the specified collection to this set.     *     * @param c collection whose elements are to be added to this set     * @return <tt>true</tt> if this set changed as a result of the call     * @throws NullPointerException if the specified collection or any     *     of its elements are null     */    public boolean addAll(Collection<? extends E> c) {        if (!(c instanceof RegularEnumSet))            return super.addAll(c);         RegularEnumSet es = (RegularEnumSet)c;        if (es.elementType != elementType) {            if (es.isEmpty())                return false;            else                throw new ClassCastException(                    es.elementType + " != " + elementType);        }         long oldElements = elements;        elements |= es.elements;        return elements != oldElements;    }     /**     * Removes from this set all of its elements that are contained in     * the specified collection.     *     * @param c elements to be removed from this set     * @return <tt>true</tt> if this set changed as a result of the call     * @throws NullPointerException if the specified collection is null     */    public boolean removeAll(Collection<?> c) {        if (!(c instanceof RegularEnumSet))            return super.removeAll(c);         RegularEnumSet es = (RegularEnumSet)c;        if (es.elementType != elementType)            return false;         long oldElements = elements;        elements &= ~es.elements;        return elements != oldElements;    }     /**     * Retains only the elements in this set that are contained in the     * specified collection.     *     * @param c elements to be retained in this set     * @return <tt>true</tt> if this set changed as a result of the call     * @throws NullPointerException if the specified collection is null     */    public boolean retainAll(Collection<?> c) {        if (!(c instanceof RegularEnumSet))            return super.retainAll(c);         RegularEnumSet<?> es = (RegularEnumSet<?>)c;        if (es.elementType != elementType) {            boolean changed = (elements != 0);            elements = 0;            return changed;        }         long oldElements = elements;        elements &= es.elements;        return elements != oldElements;    }     /**     * Removes all of the elements from this set.     */    public void clear() {        elements = 0;    }     /**     * Compares the specified object with this set for equality.  Returns     * <tt>true</tt> if the given object is also a set, the two sets have     * the same size, and every member of the given set is contained in     * this set.     *     * @param e object to be compared for equality with this set     * @return <tt>true</tt> if the specified object is equal to this set     */    public boolean equals(Object o) {        if (!(o instanceof RegularEnumSet))            return super.equals(o);         RegularEnumSet es = (RegularEnumSet)o;        if (es.elementType != elementType)            return elements == 0 && es.elements == 0;        return es.elements == elements;    }}