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 elementType is null
*/
public static > EnumSet allOf(Class elementType) {
EnumSet 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 elementType is null
*/
public static > EnumSet noneOf(Class elementType) {
//获得所有枚举项
Enum[] universe = getUniverse(elementType);
if (universe == null)
throw new ClassCastException(elementType + " not an enum");
if (universe.length <= 64)
//枚举数量小于等于64
return new RegularEnumSet(elementType, universe);
else
//枚举数量大于64
return new JumboEnumSet(elementType, universe);
}
RegularEnumSet 实例对象
class RegularEnumSet> extends EnumSet {
/**
* 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(ClasselementType, 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> extends EnumSet {
/**
* 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(ClasselementType, 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的时候,那简直就是飞一般的速度。