1700446575
1700446576
else
1700446577
1700446578
//枚举数量大于64
1700446579
1700446580
return new JumboEnumSet<E>(elementType, universe);
1700446581
1700446582
}
1700446583
1700446584
看到这里恍然大悟,Java原来是如此处理的:当枚举项数量小于等于64时,创建一个RegularEnumSet实例对象,大于64时则创建一个JumboEnumSet实例对象。
1700446585
1700446586
紧接着的问题是:为什么要如此处理呢?这还要看看这两个类之间的差异,首先看RegularEnumSet类,代码如下:
1700446587
1700446588
class RegularEnumSet<E extends Enum<E>>extends EnumSet<E>{
1700446589
1700446590
//记录所有枚举排序号,注意是long型
1700446591
1700446592
private long elements=0L;
1700446593
1700446594
//构造函数
1700446595
1700446596
RegularEnumSet(Class<E>elementType, Enum[]universe){
1700446597
1700446598
super(elementType, universe);
1700446599
1700446600
}
1700446601
1700446602
//加入所有元素
1700446603
1700446604
void addAll(){
1700446605
1700446606
if(universe.length!=0)
1700446607
1700446608
elements=-1L>>>-universe.length;
1700446609
1700446610
}
1700446611
1700446612
}
1700446613
1700446614
我们知道枚举项的排序值ordinal是从0、1、2……依次递增的,没有重号,没有跳号,RegularEnumSet就是利用这一点把每个枚举项的ordinal映射到一个long类型的每个位上的,注意看addAll方法的elments元素,它使用了无符号右移操作,并且操作数是负值,位移也是负值,这表示是负数(符号位是1)的“无符号左移”:符号位为0,并补充低位,简单地说,Java把一个不多于64个枚举项的枚举映射到了一个long类型变量上。这才是EnumSet处理的重点,其他的size方法、constains方法等都是根据elements计算出来的。想想看,一个long类型的数字包含了所有的枚举项,其效率和性能肯定是非常优秀的。
1700446615
1700446616
我们知道long类型是64位的,所以RegularEnumSet类型也就只能负责枚举项数量不大于64的枚举(这也是我们以64来举例,而不以128或512举例的原因),大于64则由JumboEnumSet处理,我们看它是怎么处理的:
1700446617
1700446618
class JumboEnumSet<E extends Enum<E>>extends EnumSet<E>{
1700446619
1700446620
//映射所有的枚举项
1700446621
1700446622
private long elements[];
1700446623
1700446624
//构造函数
[
上一页 ]
[ :1.700446575e+09 ]
[
下一页 ]