Java中的EnumSet
在Java中,我们经常会使用枚举类型(Enum)来表达一些固定不变的数据类型,比如周几、性别等等。而EnumSet则是一个用来代替传统集合(Set)实现枚举类型的工具。
EnumSet的定义
EnumSet是一个抽象类,继承自AbstractSet类,是一个在枚举类型基础上的集合类。
EnumSet的创建
我们可以通过静态方法of()来创建一个EnumSet,如下所示:
import java.util.EnumSet;
enum Weekday {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
public class EnumSetDemo {
public static void main(String[] args) {
EnumSet<Weekday> weekdays = EnumSet.of(Weekday.MONDAY, Weekday.TUESDAY, Weekday.WEDNESDAY);
System.out.println(weekdays); //[MONDAY, TUESDAY, WEDNESDAY]
}
}
在上面的代码中,我们定义了一个Weekday枚举类型,并且通过of()方法创建了一个包含MONDAY、TUESDAY、WEDNESDAY三个枚举常量的EnumSet。
除此之外,我们也可以使用EnumSet.range()方法来创建一个包含连续枚举常量的EnumSet,如下所示:
EnumSet<Weekday> weekdays = EnumSet.range(Weekday.MONDAY, Weekday.WEDNESDAY);
System.out.println(weekdays); //[MONDAY, TUESDAY, WEDNESDAY]
EnumSet的操作
EnumSet是一个集合类,因此我们可以对其进行一些集合操作,比如添加元素、删除元素、判断是否包含某个元素等等。下面是一些常用的操作:
添加元素
EnumSet<Weekday> weekdays = EnumSet.of(Weekday.MONDAY, Weekday.TUESDAY, Weekday.WEDNESDAY);
weekdays.add(Weekday.THURSDAY);
System.out.println(weekdays); //[MONDAY, TUESDAY, WEDNESDAY, THURSDAY]
在上面的代码中,我们使用add()方法向EnumSet中添加了一个枚举常量THURSDAY。
删除元素
EnumSet<Weekday> weekdays = EnumSet.of(Weekday.MONDAY, Weekday.TUESDAY, Weekday.WEDNESDAY);
weekdays.remove(Weekday.TUESDAY);
System.out.println(weekdays); //[MONDAY, WEDNESDAY]
在上面的代码中,我们使用remove()方法从EnumSet中删除了一个枚举常量TUESDAY。
判断元素是否存在
EnumSet<Weekday> weekdays = EnumSet.of(Weekday.MONDAY, Weekday.TUESDAY, Weekday.WEDNESDAY);
System.out.println(weekdays.contains(Weekday.MONDAY)); //true
System.out.println(weekdays.contains(Weekday.THURSDAY)); //false
在上面的代码中,我们使用contains()方法来判断EnumSet中是否包含某个枚举常量。
EnumSet和普通Set的区别
虽然EnumSet是在Set基础上实现的,但是和普通的Set还是有一些区别的:
1. 元素类型必须是枚举类型
EnumSet只能包含枚举类型的元素,而普通的Set是可以包含任意类型的。
2. EnumSet的迭代器是按枚举常量的顺序排序的
正如我们前面提到的,EnumSet是由枚举类型构成的,因此EnumSet中的元素是按枚举常量的顺序排序的。而普通的Set在遍历时是没有任何顺序的。
3. EnumSet支持一些高效的位集合运算
由于EnumSet底层是使用位向量(Bit Vector)实现的,因此EnumSet在进行一些特定操作时,比普通的Set更高效:
3.1 全集运算
我们可以使用EnumSet.allOf()方法来创建一个包含所有枚举元素的EnumSet。
EnumSet<Weekday> allWeekdays = EnumSet.allOf(Weekday.class);
System.out.println(allWeekdays); //[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]
上面的代码中,我们使用了allOf()方法来创建了一个包含所有Weekday枚举常量的EnumSet。
3.2 求差集
我们可以使用EnumSet.complementOf()方法来获取两个EnumSet的差集。
EnumSet<Weekday> weekdays = EnumSet.of(Weekday.MONDAY, Weekday.TUESDAY, Weekday.WEDNESDAY);
EnumSet<Weekday> weekends = EnumSet.complementOf(weekdays);
System.out.println(weekends); //[THURSDAY, FRIDAY, SATURDAY, SUNDAY]
在上面的代码中,我们使用complementOf()方法获取了与weekdays中的枚举常量不同的枚举常量所构成的EnumSet。
3.3 求交集
我们可以使用EnumSet.intersect()方法来获取两个EnumSet的交集。
EnumSet<Weekday> weekdays1 = EnumSet.of(Weekday.MONDAY, Weekday.TUESDAY, Weekday.WEDNESDAY);
EnumSet<Weekday> weekdays2 = EnumSet.of(Weekday.WEDNESDAY, Weekday.THURSDAY, Weekday.FRIDAY);
EnumSet<Weekday> weekdays = weekdays1.clone();
weekdays.retainAll(weekdays2);
System.out.println(weekdays); //[WEDNESDAY]
在上面的代码中,我们使用retainAll()方法来获取了weekdays1和weekdays2的交集。
一个关于EnumSet的小技巧:我们可以通过EnumSet.noneOf()方法来创建一个空的EnumSet。