Java 枚举项数量限定为64个以内

来源:互联网 发布:莫斯科地铁软件 编辑:程序博客网 时间:2024/04/30 16:26
        java 提供了两个枚举集合:EnumSet和EnumMap,这两个集合的使用都比较简单,EnumSet表示其元素必须是某一枚举的枚举项EnumMap表示Key值必须是某一枚举的枚举项由于枚举类的实例数量固定并且有限,相对来说EnumSet和EnumMap的效率会比其他Set和Map要高。

为什么要限定在64个枚举项以内?
虽然EnumSet很好用,但是它有一个隐藏的特点,看源代码:
    /**
     * Creates an enum set containing all of the elements in the specified
     * element type.
     *
     * @param elementType the class object of the element type for this enum
     *     set
     * @throws NullPointerException if <tt>elementType</tt> is null
     */
    public static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType) {
        EnumSet<E> result = noneOf(elementType);
        result.addAll();
        return result;
    }
    allOf通过nonof方法首先生产一个EnumSet对象,然后把所有的枚举项都加进去。    

    /**
     * Creates an empty enum set with the specified element type.
     *
     * @param elementType the class object of the element type for this enum
     *     set
     * @throws NullPointerException if <tt>elementType</tt> is null
     */
    public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
        //获得所有枚举项
        Enum[] universe = getUniverse(elementType);
        if (universe == null)
            throw new ClassCastException(elementType + " not an enum");

        if (universe.length <= 64)
            //枚举数量小于等于64
            return new RegularEnumSet<E>(elementType, universe);
        else
            //枚举数量大于64
            return new JumboEnumSet<E>(elementType, universe);
    }

RegularEnumSet 实例对象
class RegularEnumSet<E extends Enum<E>> extends EnumSet<E> {
    /**
     * Bit vector representation of this set.  The 2^k bit indicates the
     * presence of universe[k] in this set.
     */
    //记录所有枚举排序号,注意是Long型
    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;
    }


JumboEnumSet实例对象
class JumboEnumSet<E extends Enum<E>> extends EnumSet<E> {
    /**
     * Bit vector representation of this set.  The ith bit of the jth
     * element of this array represents the  presence of universe[64*j +i]
     * in this set.
     */
    //映射所有的枚举项
    private long elements[];

    // Redundant - maintained for performance
    private int size = 0;
    //构造函数
    JumboEnumSet(Class<E>elementType, Enum[] universe) {
        super(elementType, universe);
        elements = new long[(universe.length + 63) >>> 6];
    }

    void addRange(E from, E to) {
        int fromIndex = from.ordinal() >>> 6;
        int toIndex = to.ordinal() >>> 6;

        if (fromIndex == toIndex) {
            elements[fromIndex] = (-1L >>>  (from.ordinal() - to.ordinal() - 1))
                            << from.ordinal();
        } else {
            elements[fromIndex] = (-1L << from.ordinal());
            for (int i = fromIndex + 1; i < toIndex; i++)
                elements[i] = -1;
            elements[toIndex] = -1L >>> (63 - to.ordinal());
        }
        size = to.ordinal() - from.ordinal() + 1;
    }
    
    void addAll() {
        //elements 中每个元素表示64个枚举项
        for (int i = 0; i < elements.length; i++)
                elements[i] = -1;
                elements[elements.length - 1] >>>= -universe.length;
                size = universe.length;
    }

总结:
        从以上的源码分析可以看出,EnumSet提供的两个实现类都是基本的数字类型操作,其性能肯定比其他的Set类型要好很多,特别是Enum的数量少于64的时候,那简直就是飞一般的速度。



0 1
原创粉丝点击