EnumSet 原理相关

问:说说 EnumSet 怎么用,其基本原理是什么?

答:EnumSet 是一个 Set 集合的抽象类,其有两个实现类 JumboEnumSet 和 RegularEnumSet,在使用的时候放入的必须是枚举类型,其特点是速度非常快。特别注意之前有问题说过 HashSet、TreeSet 的实现原理都是对 HashMap、TreeMap 的封装实现,但是 EnumSet 的实现与 EnumMap 没有任何关系,EnumSet 的默认子类实现原理是采用了极为精简和高效的位向量方式。

EnumSet 在使用上可以自己继承 EnumSet 抽象类实现自己的特有集合,也可以通过特殊的工厂方法进行实例化(但是绝对不可以直接 new,因为是抽象类),其提供的工厂构造如下:

        //创建一个指定枚举类型的空EnumSet(RegularEnumSet/JumboEnumSet)
                >EnumSet noneOf (Class < E > elementType)
        // 创建一个初始集合包括指定枚举类型所有枚举值的EnumSet
                < E extends Enum>EnumSet allOf (Class < E > elementType)
        // 创建一个初始集合包括指定范围(枚举范围,两边都包含)的EnumSet
                < E extends Enum>EnumSet range (E from, E to )
        // 创建一个初始集合不包括指定枚举集合的EnumSet
                >EnumSet complementOf (EnumSet < E > s)
        // 创建一个初始集合包括指定ex的EnumSet
                < E extends Enum>EnumSet of (E e )   
                >EnumSet of (E e1, E e2 )
                >EnumSet of (E e1, E e2, E e3 )
                >EnumSet of (E e1, E e2, E e3, E e4 )
                >EnumSet of (E e1, E e2, E e3, E e4, E e5 )
                >EnumSet of (E first, E ...rest )
        //创建一个初始集合包括指定枚举集合的EnumSet
                >EnumSet copyOf (EnumSet < E > s)
                < E extends Enum>EnumSet copyOf (Collection < E > c)

EnumSet 的默认子类 RegularEnumSet 和 JumboEnumSet 实现原理都是基于位运算向量,位运算向量的原理就是用一个位表示一个元素的状态(元素的状态只有两种),用一组位表示一个集合的状态,每个位对应一个元素,譬如一个枚举类 DemoEnum 有6个枚举值,则 EnumSet 集合就可以通过一个 byte 字节从右到左(二进制低到高位)来表示,不用的位上用 0 填充,用的位上每个 bit 位代表一个枚举值,1 表示包含该枚举值,0 表示不含该枚举值。因此位向量能表示的枚举值个数与向量长度有关,上面例子中一个 byte 类型最多能表示 8 个枚举值,所以 EnumSet 抽象类的两个实现类 RegularEnumSet 和 JumboEnumSet 分别定义了不同的向量长度。RegularEnumSet 使用 64 位的 long 类型变量作为位向量,而 JumboEnumSet 使用一个 long 类型数组作为向量(数组内存连续),故当我们通过 EnumSet 的工厂方法创建 EnumSet 集合时 EnumSet 会通过判断枚举类的枚举值数量决定使用两个子类的哪一个,如果枚举值个数小于等于 64 就用 RegularEnumSet,大于 64 就用 JumboEnumSet。

EnumSet 核心工厂方法实现如下:

    //依据枚举类成员个数决定使用EnumSet抽象类的哪个子类 
        public static > EnumSet noneOf (Class < E > elementType) {
            Enum[] universe = getUniverse(elementType);
             ......
            if (universe.length <= 64) return new RegularEnumSet<>(elementType, universe);
            else return new JumboEnumSet<>(elementType, universe);
        }

你可能感兴趣的:(EnumSet 原理相关)