文章作者:Tyan
博客:noahsnail.com
1. EnumSet
EnumSet是Java Set接口的一个特别实现,在JDK 1.5中开始支持,Enum类型也正式引入到了Java中。与其它保存枚举常量的Set相比,EnumSet具有更好的性能,同时其也是Java中的优秀特性之一。下面从三个方面来介绍EnumSet,what,how,when。
2. What is EnumSet
EnumSet是Set接口的一个实现,它只能用来存储Enum常量或其子类,不能存储其它类型。EnumSet是设计模式中工厂方法创建实例的一个很好例子。
EnumSet被声明为abstract class类型,EnumSet有两种实现方式,RegularEnumSet和JumboEnumSet,但是这两种实现方式是包私有的,不能在包外访问,因此必须使用工厂方法来创建并返回EnumSet实例,不能通过构造函数来创建。EnumSet中提供了多种创建EnumSet实例的静态工厂方法,例如of方法(进行了函数重载),copyOf方法,noneOf方法等。
3. How EnumSet is implemented in Java
上面已经说了,EnumSet是一个抽象类,有两个具体实现:java.util.RegularEnumSet和java.util.JumboEnumSet。二者的主要区别在于前者使用long来表示元素的数量,而后者使用long[]来表示元素的数量。这二者中表示元素数量使用的是位域结构,即通过long的二进制位数来表示元素数量,例如:RegularEnumSet使用的是long表示元素数量,long数值是通过64位二进制表示的,因此其只能包含的元素最大数量为64,如果元素数目大于64,采用的是JumboEnumSet表示,JumboEnumSet的long[]中有一个long数值,就能表示64个元素,两个long数值就能表示128个元素,以此类推。
4. When to use EnumSet in Java
《Effective Java》中的Item 32讲述了一个EnumSet的使用场景,推荐去看一下。当你需要对枚举类型进行特定的分组时,你可以使用EnumSet。例如,一周中有七天,你想将周末单独分出来的时候(enum int pattern):
1 | private enum DayOfWeek{ |
5. Important points about EnumSet
一个
EnumSet中只能包含一种枚举类型。EnumSet中不能放入null元素,放入会抛出空指针异常。EnumSet是线程非安全的。EnumSet的Iterator是自动防故障和弱一致的,不会抛出并发修改异常,即在迭代过程的中的修改结果不一定会在迭代过程中显示。EnumSet是高性能的Java集合。由于是基于数组的访问,因此add,contains,next方法的时间复杂度为O(1)。存储枚举常量时使用
EnumSet而不要用HashSet。
6. Source Code of EnumSet
EnumSet:
1 | public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> implements Cloneable, java.io.Serializable { |
RegularEnumSet:
1 | class RegularEnumSet<E extends Enum<E>> extends EnumSet<E> { |
JumboEnumSet:
1 | class JumboEnumSet<E extends Enum<E>> extends EnumSet<E> { |
7. Example of EnumSet
1 | import java.util.EnumSet; |
参考资料:
1、https://jaxenter.com/enumset-in-java-regularenumset-vs-jumboenumset-106051.html
2、Effective Java 2.0版本中的Item 1,本文就是在看《Effective Java》时看到的EnumSet,才想要仔细研究一下EnumSet的。Item 32讲述了EnumSet的使用场景。
3、http://brokendreams.iteye.com/blog/2267485
4、http://javarevisited.blogspot.kr/2014/03/how-to-use-enumset-in-java-with-example.html