EnumSet 到底是什么意思?

我举个例子:

import java.util.EnumSet;
import java.util.Iterator;


public class SizeSet {


public static void main(String[] args) {
EnumSet largeSize = EnumSet.of(Size.XL,Size.XXL,Size.XXXL);
for(Iterator it = largeSize.iterator();it.hasNext();){
Size size = (Size)it.next();
System.out.println(size);
}
}
}




enum Size {
S, M, L, XL, XXL, XXXL;


}

在这段代码中,我可以理解 Enum 创建了一个大小的 Enum 类型。

我的问题是: largeSize是 EnumSet 类型的对象吗?这到底意味着什么?我真的想更好地理解它。

63722 次浏览

对于任何变量,其类型都可以在其声明中找到:

EnumSet largeSize

因此,是的,largeSize(因为它是一个集合,所以应该命名为 largeSizes)是 EnumSet类型。它也应该被泛化,因此被声明为

EnumSet<Size> largeSizes

这意味着,largeSizesEnumSet类型的。EnumSet是一个包含特定枚举类型的枚举实例的 Set,它比其他 Set实现(如 HashSetTreeSet等)更有效率。要知道什么是 EnumSet,请阅读它的 空气污染指数

举例如下:

....
public static final String S = "s";
public static final String M = "m";
public static final String L = "l";
....


Set<String> sizeSet = new HashSet<String>();
sizeSet.add(S);
sizeSet.add(M);

那么,在上面的例子中 sizeSet 是什么呢?

EnumSet 与上面的示例没有什么不同,只是 EnumSet 是一个特殊的 Set 实现,可以使用枚举类型并对其进行优化,仅此而已。

简化代码

EnumSet<Size> largeSize = EnumSet.of(Size.XXXL, Size.XXL, Size.XL, Size.L);
for(Size size: largeSize)
System.out.print(size+" ");

您可以看到,largeSize 是一个常规的 Set,除了用于存储 Enums。这有什么不同?首先,JVM 知道集合中所有可能的值,这意味着它可以使用位图来代替存储所有对象,其中1表示项目存在,0表示项目不存在。这也意味着集合的顺序是序数值的顺序,也就是它们被定义的顺序。这就是为什么这些指纹

L XL XXL XXXL

如果你想知道更多的细节,我建议你阅读这个类的源代码。

它可以快速地将任何 Enum 元素转换成一个集合,EnumSet 是另一种类型的 Set。

public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH }


EnumSet.of(Style.BOLD, Style.ITALIC);

EnumSet 专门用于存储枚举类型元素并对其进行快速迭代。 艾格。

for (Day d : EnumSet.range(Day.MONDAY, Day.FRIDAY))
System.out.println(d);

上面的代码片段将显示从星期一到星期五的星期几。

根据 甲骨文文件

枚举集在内部表示为位向量。这种表示非常紧凑和高效。

可读,输入安全,低内存占用... 你还想要什么?

简单的 Enum是一个值列表,一次只能从中选择 。使用你的例子,一个尺寸可以只是 S,M,L 等任何给定的服装之一。您可以使用简单的常量代替 Enum,但是这样做具有可读性、更容易维护和严格的类型检查等优点。

当您需要一个变量同时假设多个 Enum值时,将使用 EnumSet。例如,在屏幕上使用的字体可以同时是 大胆斜体EnumSet允许您添加各种值,并测试是否在任何给定时间实际设置了其中一个值。如果您是从其他编程语言来到 Java 的,那么这就是通常称为 旗帜的功能。

比较两者:

enum Size { S, M, L, XL, XXL, XXXL }
Size currentSize;
...
currentSize = Size.S;
...
if (currentSize == Size.S) ...

定义,赋值,然后检查单个 Enum值。

enum FontStyle { Bold, Italic, Underline, Strikethrough }
EnumSet<FontStyle> currentStyle;
...
currentStyle = EnumSet.of(FontStyle.Bold, FontStyle.Italic);
...
if (currentStyle.contains(FontStyle.Italic)) ...

定义,同时分配两个 Enum值,然后检查其中一个是否实际设置。

EnumSet largeSize

EnumSet largeSize 是一组包含 XL、 XXL 和 XXXL 的 Enum 值。

Size

Size 是一个 Enum 类型的类,具有常量值 S、 M、 L、 XL、 XXL、 XXXL。

largeSize.iterator()

EnumSet 的迭代器是自然顺序,即最初声明枚举值的顺序。

  • EnumSet 类是 Java集合框架的成员并且不是同步的。
  • 这是一个高性能的集合实现,它们比 HashSet.
  • 每个 EnumSet 实例的所有元素都必须是 单一枚举类型单一枚举类型。

了解更多请阅读 api 文档: http://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html

来自约书亚 · 布洛赫的书,用他自己的话说:

Util 包提供了 EnumSet 类来有效地表示 从单个枚举类型中提取的值集 集接口,提供所有的丰富性,类型安全和 与其他 Set 实现的互操作性 在内部,每个 EnumSet 都表示为一个位向量 基础枚举类型只有64个或更少的元素——而且大多数都有 整个 EnumSet 用一个 long 表示,所以它的性能与位字段相当。批量经营, 例如 RemoveAll 和 retainAll,都是使用位智能实现的 算术,就像您将手动处理位字段一样 与手动钻头的丑陋和易错性隔离 EnumSet 为您完成最困难的工作。

所以我们可以这么做。

public class SizeSet {


public enum Size {S, M, L, XL, XXL, XXXL}


public void applySize(Set<Size> sizes){}


}

客户端代码调用它可能会执行以下操作

SizeSet largeSizeSet = new SizeSet();
largeSizeSet.applySize(EnumSet.of(Size.L, Size.XXL, Size.XXL));

注意,applicySize 方法使用的是 Set<Size>而不是 EnumSet<Size> 显而易见,而且很可能客户机会将 EnumSet 传递给方法,因此接受接口而不是具体的实现是一种很好的做法。

EnumSet是一个专门用于处理枚举类的 集合,它实现了 Set接口,并从 AbstractSet扩展:

enter image description here

当您计划使用 EnumSet 时,您必须考虑以下几点:

  1. 它只能包含枚举值和所有必须属于的值 相同的枚举
  2. 它不允许添加 null 值,为此抛出 NullPointerException
  3. 它不是线程安全的,所以 如果需要,我们需要在外部同步它
  4. 元素是 按照它们在枚举中声明的顺序存储
  5. 它使用在副本上工作的故障安全迭代器,所以它不会抛出 时修改集合时发生 不断重复

现在,EnumSet largeSize部分是 变量声明,所以是的,它的类型是 EnumSet。请注意,为了更好的类型安全性,您可以在集合中添加元素的类型: EnumSet<Size>

看看这篇文章到 了解更多关于 EnumSet 的信息