努力的小胖学习记录(九)------EnumSet

  1. 什么是EnumSet
    EnumSet继承结构图
    从上图可以看出,EnumSet是个抽象类,继承AbstractSet,然后有两个具体子类分别为RegularEnumSet和JumboEnumSet,并且EnumSet只能存放Enum类别的对象。另外我们再看Thinking in java的一句话:EnumSet的设计充分考虑到了速度因素,因为它必须与非常高效的bit标志相竞争。从这句话可以看出,EnumSet是非常之快的,事实上,它的查询速度和插入速度都为O(1)。

  2. 获取EnumSet对象的方法
    因为EnumSet是抽象类,不可以直接new,而是采用静态工厂方法来产生对象的,下面介绍几个常用的静态方法:
    noneOf(Class elementType):创建一个指定枚举类型的EnumSet,不含任何元素
    allOf(Class elementType):创建一个指定枚举类型的EnumSet,包含所有元素
    后面一些的其他的方法都是基于上面两个的整合

  3. 为什么EnumSet很快
    我们HashSet是基于散列表实现的,TreeSet是基于树实现的,它们的速度都没有EnumSet快,因为它的内部是基于long值作为比特向量,是直接通过比较而二进制来实现的,所以会超级的快。直接看源码:
    3.1 获取实例的工厂方法
    noneOf
    从方法很容易看出,如果这个这个枚举的数量小于等于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。

  4. 结语
    虽然EnumSet的应用场景很少,但是我觉得这个东西还是有很多的参考价值的,不管是从设计模式上还是从提高性能的思路上,都有很多值得学习的,这个世上不缺好的东西,只缺善于发现的眼睛。另外如果大家想深入研究的话,可以看该博文具体详情可参考该博文

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值