72

我有以下示例:

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 类型的 Sizes。

我的问题是:是largeSizeEnumSet 类型的对象吗?它的真正含义是什么?我真的很想更好地理解它。

4

10 回答 10

48

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

EnumSet largeSize

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

EnumSet<Size> largeSizes

它的意思是,它largeSizes是 type EnumSet。AnEnumSet是一个Set包含特定枚举类型的枚举实例的 a,它以比其他Set实现(如HashSetTreeSet等)更有效的方式。要知道 anEnumSet是什么,请阅读它的API

于 2012-08-06T08:59:11.680 回答
44

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

EnumSet当您需要一个变量同时假设多个值时,将使用An Enum。例如,您在屏幕上写入的字体可以同时是粗体斜体。AnEnumSet将允许您添加各种值并测试其中一个值是否在任何给定时间实际设置。如果您是从其他编程语言接触 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值,然后检查其中一个是否实际设置。

于 2016-01-03T12:57:16.560 回答
40

简化您的代码

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

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

L XL XXL XXXL

如果您想了解更多详细信息,我建议您阅读本课程的源代码。

于 2012-08-06T09:22:13.200 回答
16

来自 Joshua Bloch 的书本身和他自己的话:

java.util 包提供 EnumSet 类来有效地表示从单个枚举类型中提取的值集。此类实现 Set 接口,提供与任何其他 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));

请注意,applySize 方法采用的是Set<Size>而不是EnumSet<Size>. 虽然很明显并且很可能客户端会将 EnumSet 传递给方法,但接受接口而不是具体实现是一种很好的做法。

于 2016-08-16T14:04:31.870 回答
7

EnumSet 专门用于存储枚举类型元素并快速迭代它。例如。

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

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

于 2015-01-09T08:43:47.153 回答
5

根据Oracle 文档

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

可读性强、类型安全、内存占用少……您还想要什么?

于 2015-02-04T18:58:02.047 回答
3

给定以下示例:

....
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 实现,可以与枚举类型一起使用并对其进行优化,仅此而已。

于 2012-08-06T09:15:24.133 回答
3
EnumSet largeSize

EnumSet largeSize 是一组枚举值,其中包含 XL、XXL 和 XXXL。

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

于 2016-08-10T13:12:02.233 回答
0

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

在此处输入图像描述

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

  1. 它只能包含枚举值,并且所有值必须属于同一个枚举
  2. 它不允许添加空值,抛出 NullPointerException 试图这样做
  3. 它不是线程安全的,所以如果需要我们需要在外部同步它
  4. 元素按照在枚举中声明的顺序存储
  5. 它使用适用于副本的故障安全迭代器,因此如果在迭代集合时修改了集合,它不会抛出 ConcurrentModificationException

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

查看本文以了解有关 EnumSet的更多信息。

于 2019-06-15T10:16:02.313 回答
-2

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

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

EnumSet.of(Style.BOLD, Style.ITALIC);
于 2013-07-02T12:50:58.533 回答