-
什么是EnumSet
从上图可以看出,EnumSet是个抽象类,继承AbstractSet,然后有两个具体子类分别为RegularEnumSet和JumboEnumSet,并且EnumSet只能存放Enum类别的对象。另外我们再看Thinking in java的一句话:EnumSet的设计充分考虑到了速度因素,因为它必须与非常高效的bit标志相竞争。从这句话可以看出,EnumSet是非常之快的,事实上,它的查询速度和插入速度都为O(1)。 -
获取EnumSet对象的方法
因为EnumSet是抽象类,不可以直接new,而是采用静态工厂方法来产生对象的,下面介绍几个常用的静态方法:
noneOf(Class elementType):创建一个指定枚举类型的EnumSet,不含任何元素
allOf(Class elementType):创建一个指定枚举类型的EnumSet,包含所有元素
后面一些的其他的方法都是基于上面两个的整合 -
为什么EnumSet很快
我们HashSet是基于散列表实现的,TreeSet是基于树实现的,它们的速度都没有EnumSet快,因为它的内部是基于long值作为比特向量,是直接通过比较而二进制来实现的,所以会超级的快。直接看源码:
3.1 获取实例的工厂方法
从方法很容易看出,如果这个这个枚举的数量小于等于64的时候,则直接用RegularEnumSet,否则JumboEnumSet。其实这两个类还是有很多共性的,主要的区别是因为一个long值只有64位,所以RegularEnumSet是只有一个long值作为比特向量,而JumboEnumSet使用long数组作为比特向量。因为两个类很多方法是差不多的,主要是一些针对下标超过64的会相应的定位到下一个数组位置,为了简单,我就是只为大家讲解RegularEnumSet的一些方法,如果大家感兴趣的话,直接去另外一个源码。
3.2 新增add
新增其实很简单,就是把1带符号左移当前枚举值的下标(假如下标为3)得到的值v1(0X100)与原先的值elements(假如是0X001)进行或运算,则得到后的新值为0x101,则代表当前枚举的第一个和第三个放入了容器。这就是为什么EnumSet很快的原因,因为没有真的放入一个对象,只是简单的记录一个标志位。
3.3 移除remove
其实也是差不多的,先进行类型校验,再根据下标左移得到值v1(0x100),再把v1取非得到v2(0x011),在和elements(0x101)进行与运算得到最终的值(0x001)。
3.4 包含contains
前面还是一样的方法获取到v1(0x100),然后与elements(0x001)取与得到v2(0x000),再判断v2是不是!=0。 -
结语
虽然EnumSet的应用场景很少,但是我觉得这个东西还是有很多的参考价值的,不管是从设计模式上还是从提高性能的思路上,都有很多值得学习的,这个世上不缺好的东西,只缺善于发现的眼睛。另外如果大家想深入研究的话,可以看该博文具体详情可参考该博文。
努力的小胖学习记录(九)------EnumSet
最新推荐文章于 2020-06-30 14:57:31 发布