Java容器之EnumSet源码分析
一、概述
EnumSet
是一个抽象类,不能直接使用,该类有两个子类,RegularEnumSet和JumboEnumSet。即枚举值的个数小于等于64
时使用RegularEnumSet
,大于64
时使用JumboEnumSet
。
这两个子类都是非public
的,只能包内访问。
当EnumSet
需要进行一个操作时首先调用noneOf
这个方法,获得一个RegularEnumSet
或者JumboEnumSet
对象,随后在执行一些操作。
二、源码分析
2.1 属性
/**
* 枚举的类型
*/
final Class<E> elementType;
/**
* 枚举类E的所有枚举值
*/
final Enum<?>[] universe;
EnumSet
定义了多个静态的工具类方法,其中核心方法如add
的实现都留给了子类,下面逐一说明想法方法的实现。
2.2 创建EnumSet
noneOf
、allOf
、of
、range
这些方法都是用来创建EnumSet
的。
2.2.1 noneOf方法
noneOf
返回一个空的EnumSet
//返回一个空的EnumSet
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");
if (universe.length <= 64)
return new RegularEnumSet<>(elementType, universe);
else
return new JumboEnumSet<>(elementType, universe);
}
//返回指定枚举类的所有枚举值
private static <E extends Enum<E>> E[] getUniverse(Class<E> elementType) {
return SharedSecrets.getJavaLangAccess()
.getEnumConstantsShared(elementType);
}
2.2.2 allOf方法
allOf
返回一个包含指定枚举类所有枚举值的EnumSet
//返回一个包含了所有枚举值的EnumSet
public static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType) {
EnumSet<E> result = noneOf(elementType);
//子类实现
result.addAll();
return result;
}
2.2.3 of方法
of
方法返回一个包含一个或者多个的指定枚举值的EnumSet
//创建只包含一个指定枚举值的EnumSet,有多个重载版本,枚举值从1个到5个
public static <E extends Enum<E>> EnumSet<E> of(E e) {
EnumSet<E> result = noneOf(e.getDeclaringClass());
//子类实现
result.add(e);
return result;
}
@SafeVarargs
public static <E extends Enum<E>> EnumSet<E> of(E first, E... rest) {
EnumSet<E> result = noneOf(first.getDeclaringClass());
result.add(first);
//rest是不定数量的数组,将其中的元素都添加到Set中
for (E e : rest)
result.add(e);
return result;
}
2.2.4 range方法
range
返回一个包含指定范围的枚举值的EnumSet
//创建包含指定范围内的枚举值的EnumSet
public static <E extends Enum<E>> EnumSet<E> range(E from, E to) {
if (from.compareTo(to) > 0)
throw new IllegalArgumentException(from + " > " + to);
EnumSet<E> result = noneOf(from.getDeclaringClass());
//子类实现
result.addRange(from, to);
return result;
}
2.3 复制指定的EnumSet
2.3.1 copyOf方法
copyOf
用于复制指定的EnumSet
,
public static <E extends Enum<E>> EnumSet<E> copyOf(EnumSet<E> s) {
return s.clone();
}
public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c) {
if (c instanceof EnumSet) {
//如果是EnumSet
return ((EnumSet<E>)c).clone();
} else {
if (c.isEmpty())
throw new IllegalArgumentException("Collection is empty");
//如果不是EnumSet,则遍历其中的元素,逐一添加到EnumSet中
Iterator<E> i = c.iterator();
E first = i.next();
EnumSet<E> result = EnumSet.of(first);
while (i.hasNext())
result.add(i.next());
return result;
}
}
public EnumSet<E> clone() {
try {
//调用Object的clone方法
return (EnumSet<E>) super.clone();
} catch(CloneNotSupportedException e) {
throw new AssertionError(e);
}
}
2.3.2 complementOf方法
complementOf
返回原EnumSet
中不包含的枚举值。
//返回的EnumSet中包含了所有的枚举值
public static <E extends Enum<E>> EnumSet<E> complementOf(EnumSet<E> s) {
EnumSet<E> result = copyOf(s);
//complement会补齐所有s中不包含的枚举值,由子类实现
result.complement();
return result;
}
三、案例
3.1 例1
enum Name{
SHL,
ABC,
DEF,
AVC,
DNG
}
@Test
public void test() throws Exception {
//返回一个空的EnumSet
EnumSet<Name> names = EnumSet.noneOf(Name.class);
System.out.println(names);
//返回一个包含了所有枚举值的EnumSet
names = EnumSet.allOf(Name.class);
System.out.println(names);
//返回一个包含了指定枚举值的EnumSet
names = EnumSet.of(Name.ABC, Name.DEF);
System.out.println(names);
//返回一个包含了指定范围的枚举值的EnumSet,起始值都包含
names = EnumSet.range(Name.ABC, Name.AVC);
System.out.println(names);
}
输出如下:
[]
[SHL, ABC, DEF, AVC, DNG]
[ABC, DEF]
[ABC, DEF, AVC]
3.2 例2
@Test
public void test2() throws Exception {
EnumSet<Name> names = EnumSet.allOf(Name.class);
System.out.println(names);
EnumSet<Name> names2=EnumSet.copyOf(names);
System.out.println(names2);
names.remove(Name.SHL);
names2.remove(Name.DNG);
System.out.println(names);
System.out.println(names2);
EnumSet<Name> names3 = EnumSet.complementOf(names);
System.out.println(names3);
}
其输出如下:
[SHL, ABC, DEF, AVC, DNG]
[SHL, ABC, DEF, AVC, DNG]
[ABC, DEF, AVC, DNG]
[SHL, ABC, DEF, AVC]
[SHL]
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器