EnumSet到底是什么意思?


69

我有以下示例:

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类型的对象吗?到底是什么意思 我真的很想更好地理解它。

Answers:


45

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

EnumSet largeSize

是的,largeSizelargeSizes由于它是一个集合,因此应命名)为type EnumSet。它也应该被泛化,因此被声明为

EnumSet<Size> largeSizes

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


1
所以这有点像枚举内的枚举?表示另一个对象(largeSizes),它代表对象的一部分(大小)?
亚当

3
不,这是一组枚举值。largeSizes是包含XL,XXL和XXXL的集合。您可以将其替换为HashSet,除了性能和内存消耗外,它不会改变任何其他内容。Size不是对象。这是一堂课。此类定义了几个常量:类型的L,XL,XXL等Size
JB Nizet 2012年

我不太了解...如果Size(应该是Sizes)是一个对象,为什么它看起来不像这样:Enum Sizes = new Enum; ?然后是第一个代码的最后3行?如果我可以将“大小”对象设为“大小”,则表示“大小”应该是一个类...。–
亚当

9
Size不应该Sizes。XL是一个Size,而不是一个SizesSizeNOT一个对象。这是一堂课。Size.XL是该类的6个实例之一Size。根据定义,枚举是仅具有固定数量的实例的类(在这种情况下为S,M,... XXXL)。您无法创建枚举的新实例,否则它将不再是枚举。Size 一类。所有枚举都是类,但是以不同的方式定义。
JB Nizet 2012年

43

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

EnumSet当您需要一个变量同时采用多个Enum值时,将使用an 。例如,您在屏幕上写入的字体可以同时为粗体斜体。AnEnumSet将允许您添加各种值并测试是否在任何给定时间实际设置了其中之一。如果您是通过其他编程语言来学习Java的,那么此功能通常称为flags

比较两者:

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值,然后检查是否实际设置了其中一个。


40

简化代码

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

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

L XL XXL XXXL

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


15

摘自约书亚·布洛赫(Joshua Bloch)的书,并用他自己的话说:

java.util包提供了EnumSet类,以有效地表示从单个枚举类型得出的值集。此类实现Set接口,提供您通过其他Set实现获得的所有丰富性,类型安全性和互操作性。但是在内部,每个EnumSet都表示为一个位向量。如果基础枚举类型具有64个或更少的元素-并且大多数元素都包含-整个EnumSet用单个long表示,则其性能可与位字段的性能相媲美。批量操作(例如removeAll和keepAll)是使用按位算术实现的,就像您将手动对位字段进行操作一样。但是您可以避免手动位旋转的丑陋性和错误倾向。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传递给该方法,但最好的做法是接受接口而不是具体的实现。


7

EnumSet特别用于存储枚举类型元素并快速对其进行迭代。例如。

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

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


5

根据Oracle文档

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

可读性强,输入安全,内存占用少...您还想要什么?


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


3
EnumSet largeSize

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

Size 

大小是Enum类型的一类,具有常量S,M,L,XL,XXL,XXXL。

largeSize.iterator()

EnumSet的Iterator遵循自然顺序,即最初声明枚举值的顺序。

  • EnumSet类是Java Collections Framework的成员,并且未同步。
  • 它是高性能的集实现,它们比HashSet快得多。
  • 每个EnumSet实例的所有元素都必须是单个枚举类型的元素。

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


0

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

在此处输入图片说明

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

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

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

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


-2

它可以快速将所有Enum元素转换为集合,EnumSet是Set的另一类型。

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

EnumSet.of(Style.BOLD, Style.ITALIC);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.