1、EnumSet分析
EnumSet是抽象类
,主要通过底层的两个类进行操作内部使用位向量,表示很简洁,节省空间
2、实现原理
采用位向量实现
对象内部组成
//表示类型信息
final Class<E> elementType;
//表示枚举类的所有枚举值
//EnumSet字舍恩没有记录元素个数的变量,也没有位向量
//它们是子类维护的
final Enum<?>[] universe;
3、创建对象
与TreeSet/HashSet不同,
EnumSet
是一个抽象类,不能直接通过new创建;但是它由大量的静态方法可以创建对象
3.1、 public static <E extends Enum> EnumSet noneOf
public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
Enum<?>[] universe = getUniverse(elementType);
//加入键为空则包错
if (universe == null)
throw new ClassCastException(elementType + " not an enum");
//小于64使用 RegularEnumSet 自了一
if (universe.length <= 64)
return new RegularEnumSet<>(elementType, universe);
else
//大于64 使用 JumboEnumSet 子类
return new JumboEnumSet<>(elementType, universe);
}
//RegularEnumSet构造方法
//调用父类变量为 实例变量赋值
RegularEnumSet(Class<E>elementType, Enum<?>[] universe) {
super(elementType, universe);
}
//JumboEnumSet构造方法
JumboEnumSet(Class<E>elementType, Enum<?>[] universe) {
super(elementType, universe);
//根据元素根数分配足够长度的long数组
elements = new long[(universe.length + 63) >>> 6];
}
其他的工厂方法基本都是调用noneOf方法先构造一个集合,然后再调用添加方法
3、add方法
RegularEnumSet的add方法
public boolean add(E e) {
typeCheck(e);
long oldElements = elements;
//主要代码是按位操作
//将e元素对应的位设置为1,与现有的位变量elements相或,就表示添加了e
elements |= (1L << ((Enum<?>)e).ordinal());
return elements != oldElements;
}
JumboEnumSet的add方法
ublic boolean add(E e) {
typeCheck(e);
//与RegularEnumSet的add方法的区别就是:
//它先找到对应的数组位置,eOrdinal>>>6就是eOrdinal除以64
int eOrdinal = e.ordinal();
int eWordNum = eOrdinal >>> 6;
//有了索引的之后,其他操作与RegularEnumSet就类似
long oldElements = elements[eWordNum];
elements[eWordNum] |= (1L << eOrdinal);
boolean result = (elements[eWordNum] != oldElements);
if (result)
size++;
return result;
}
4、remove方法
public boolean remove(Object e) {
if (e == null)
return false;
Class<?> eClass = e.getClass();
if (eClass != elementType && eClass.getSuperclass() != elementType)
return false;
long oldElements = elements;
//取反,该代码将元素e对应的位设置为0,这样就完成了删除
elements &= ~(1L << ((Enum<?>)e).ordinal());
return elements != oldElements;
}
5、contains方法
public boolean contains(Object e) {
if (e == null)
return false;
Class<?> eClass = e.getClass();
if (eClass != elementType && eClass.getSuperclass() != elementType)
return false;
//按位与操作 不为0 则表示包含
return (elements & (1L << ((Enum<?>)e).ordinal())) != 0;
}