EnumSet 是一个与枚举类型一起使用的专用 Set 实现。枚举set中所有元素都必须来自单个枚举类型(即必须是同类型,且该类型是Enum的子类)。
枚举类型在创建 set 时显式或隐式地指定。枚举 set 在内部表示为位向量。 此表示形式非常紧凑且高效。此类的空间和时间性能应该很好,
足以用作传统上基于 int 的“位标志”的替换形式,具有高品质、类型安全的优势。
如果指定的 collection 也是一个枚举 set,则批量操作(如 containsAll 和 retainAll)也应运行得非常快。
由 iterator 方法返回的迭代器按其自然顺序 遍历这些元素(该顺序是声明枚举常量的顺序)。
返回的迭代器是弱一致的:它从不抛出 ConcurrentModificationException,也不一定显示在迭代进行时发生的任何 set 修改的效果。
不允许使用 null 元素。试图插入 null 元素将抛出 NullPointerException。但是,
试图测试是否出现 null 元素或移除 null 元素将不会抛出异常。
像大多数 collection 一样,EnumSet 是不同步的。如果多个线程同时访问一个枚举 set,
并且至少有一个线程修改该 set,则此枚举 set 在外部应该是同步的。这通常是通过对自然封装该枚举 set 的对象执行同步操作来完成的。
如果不存在这样的对象,则应该使用 Collections.synchronizedSet(java.util.Set) 方法来“包装”该 set。
最好在创建时完成这一操作,以防止意外的非同步访问:
Set<MyEnum> s = Collections.synchronizedSet(EnumSet.noneOf(Foo.class));
实现注意事项:所有基本操作都在固定时间内执行。虽然并不保证,但它们很可能比其 HashSet 副本更快。
如果参数是另一个 EnumSet 实例,则诸如 addAll() 和 AbstractSet.removeAll(java.util.Collection) 之类的批量操作
也会在固定时间内执行。
注意1 :不允许使用 null 元素。试图插入 null 元素将抛出 NullPointerException。但是,
试图测试是否出现 null 元素或移除 null 元素将不会抛出异常。
注意2 :EnumSet是不同步的。不是线程安全的。
注意3 :EnumSet的本质就为枚举类型定制的一个Set,且枚举set中所有元素都必须来自单个枚举类型。
注意4 :关于EnumSet的存储,文档中提到是这样的。 “枚举 set 在内部表示为位向量。”
我想它应该是用一个bit为来表示的于之对应的枚举变量是否在集合中。
比如:0x1001
假如约定从低位开始,就表示第0个,和第三个枚举类型变量在EnumSet中。
这样的话空间和时间性能也就应该很好。
注意5 :至于Enum的枚举常量的位置(序数)可以用Enum的ordinal()方法得到。
注意6 :在jdk内部可以一个数组的形式一个枚举的枚举常量。
下面是来自来JDK中RegularEnumSet.java的一个示例
private static <E extends Enum<E>> E[] getUniverse(Class<E> elementType) {
return SharedSecrets.getJavaLangAccess()
.getEnumConstantsShared(elementType);
}
注意7 :元素属于哪种枚举类型必须在创建 set 时显式或隐式地指定.
注意8 :关于枚举类型的更多知识可参考《枚举类型》
实例1
import java.util.Comparator;
import java.util.EnumSet;
import java.util.Random;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
System.out.println("EnumSet.noneOf");
EnumSet<Student> set=EnumSet.noneOf(Student.class);
set.add(Student.HARRY);
set.add(Student.ROBBIE);
set.add(Student.ROBIN);
for (Student p:set)
System.out.println(p);
set.clear();
System.out.println("EnumSet.allOf");
set=EnumSet.allOf(Student.class);
for (Student p:set)
System.out.println(p);
set.clear();
System.out.println("EnumSet.Of one");
set=EnumSet.of(Student.ROBIN);
for (Student p:set)
System.out.println(p);
System.out.println("EnumSet.Of two");
set=EnumSet.of(Student.ROBIN,Student.HARRY);
for (Student p:set)
System.out.println(p);
}
}
enum Student
{
ROBIN("robin"),
HARRY("harry",40),
ROBBIE("robbie");
String name;
int age;
private Student(String name)
{
this(name,0);
}
private Student(String name,int age)
{
this.name=name;
this.age=age;
}
public String toString()
{
return name;
}
}
枚举类型在创建 set 时显式或隐式地指定。枚举 set 在内部表示为位向量。 此表示形式非常紧凑且高效。此类的空间和时间性能应该很好,
足以用作传统上基于 int 的“位标志”的替换形式,具有高品质、类型安全的优势。
如果指定的 collection 也是一个枚举 set,则批量操作(如 containsAll 和 retainAll)也应运行得非常快。
由 iterator 方法返回的迭代器按其自然顺序 遍历这些元素(该顺序是声明枚举常量的顺序)。
返回的迭代器是弱一致的:它从不抛出 ConcurrentModificationException,也不一定显示在迭代进行时发生的任何 set 修改的效果。
不允许使用 null 元素。试图插入 null 元素将抛出 NullPointerException。但是,
试图测试是否出现 null 元素或移除 null 元素将不会抛出异常。
像大多数 collection 一样,EnumSet 是不同步的。如果多个线程同时访问一个枚举 set,
并且至少有一个线程修改该 set,则此枚举 set 在外部应该是同步的。这通常是通过对自然封装该枚举 set 的对象执行同步操作来完成的。
如果不存在这样的对象,则应该使用 Collections.synchronizedSet(java.util.Set) 方法来“包装”该 set。
最好在创建时完成这一操作,以防止意外的非同步访问:
Set<MyEnum> s = Collections.synchronizedSet(EnumSet.noneOf(Foo.class));
实现注意事项:所有基本操作都在固定时间内执行。虽然并不保证,但它们很可能比其 HashSet 副本更快。
如果参数是另一个 EnumSet 实例,则诸如 addAll() 和 AbstractSet.removeAll(java.util.Collection) 之类的批量操作
也会在固定时间内执行。
试图测试是否出现 null 元素或移除 null 元素将不会抛出异常。
我想它应该是用一个bit为来表示的于之对应的枚举变量是否在集合中。
比如:0x1001
假如约定从低位开始,就表示第0个,和第三个枚举类型变量在EnumSet中。
这样的话空间和时间性能也就应该很好。
下面是来自来JDK中RegularEnumSet.java的一个示例
private static <E extends Enum<E>> E[] getUniverse(Class<E> elementType) {
return SharedSecrets.getJavaLangAccess()
.getEnumConstantsShared(elementType);
}
Enumset
是个虚类,我们只能通过它提供的静态方法来返回
Enumset
的实现类的实例。
返回EnumSet的两种不同的实现
:如果EnumSet大小小于64,
就返回RegularEnumSet实例(当然它继承自EnumSet),这个EnumSet实际上至用了一个long来存储这个EnumSet。
如果 EnumSet大小大于等于64,则返回JumboEnumSet实例,它使用一个long[]来存储。这样做的好处很明显: 大多数情况下返回的RegularEnumSet效率比JumboEnumSet高很多。
公共方法
Public Methods | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
static <E extends Enum<E>> EnumSet<E> |
allOf(
Class<E> elementType)
Creates an enum set filled with all the enum elements of the specified
elementType .
| ||||||||||
EnumSet<E> |
clone()
Creates a new enum set with the same elements as those contained in this enum set.
| ||||||||||
static <E extends Enum<E>> EnumSet<E> |
complementOf(
EnumSet<E> s)
Creates an enum set.
| ||||||||||
static <E extends Enum<E>> EnumSet<E> |
copyOf(
EnumSet<E> s)
Creates an enum set.
| ||||||||||
static <E extends Enum<E>> EnumSet<E> |
copyOf(
Collection<E> c)
Creates an enum set.
| ||||||||||
static <E extends Enum<E>> EnumSet<E> |
noneOf(
Class<E> elementType)
Creates an empty enum set.
| ||||||||||
static <E extends Enum<E>> EnumSet<E> |
of(E e1, E e2, E e3, E e4)
Creates a new enum set, containing only the specified elements.
| ||||||||||
static <E extends Enum<E>> EnumSet<E> |
of(E start, E... others)
Creates a new enum set, containing only the specified elements.
| ||||||||||
static <E extends Enum<E>> EnumSet<E> |
of(E e)
Creates a new enum set, containing only the specified element.
| ||||||||||
static <E extends Enum<E>> EnumSet<E> |
of(E e1, E e2)
Creates a new enum set, containing only the specified elements.
| ||||||||||
static <E extends Enum<E>> EnumSet<E> |
of(E e1, E e2, E e3, E e4, E e5)
Creates a new enum set, containing only the specified elements.
| ||||||||||
static <E extends Enum<E>> EnumSet<E> |
of(E e1, E e2, E e3)
Creates a new enum set, containing only the specified elements.
| ||||||||||
static <E extends Enum<E>> EnumSet<E> |
range(E start, E end)
Creates an enum set containing all the elements within the range defined by
start and
end (inclusive).
|
import java.util.Comparator;
import java.util.EnumSet;
import java.util.Random;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
System.out.println("EnumSet.noneOf");
EnumSet<Student> set=EnumSet.noneOf(Student.class);
set.add(Student.HARRY);
set.add(Student.ROBBIE);
set.add(Student.ROBIN);
for (Student p:set)
System.out.println(p);
set.clear();
System.out.println("EnumSet.allOf");
set=EnumSet.allOf(Student.class);
for (Student p:set)
System.out.println(p);
set.clear();
System.out.println("EnumSet.Of one");
set=EnumSet.of(Student.ROBIN);
for (Student p:set)
System.out.println(p);
System.out.println("EnumSet.Of two");
set=EnumSet.of(Student.ROBIN,Student.HARRY);
for (Student p:set)
System.out.println(p);
}
}
enum Student
{
ROBIN("robin"),
HARRY("harry",40),
ROBBIE("robbie");
String name;
int age;
private Student(String name)
{
this(name,0);
}
private Student(String name,int age)
{
this.name=name;
this.age=age;
}
public String toString()
{
return name;
}
}