EnumSet真正意味着什么?

Ada*_*dam 66 java enums object 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;

}
Run Code Online (Sandbox Code Playgroud)

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

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

JB *_*zet 43

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

EnumSet largeSize
Run Code Online (Sandbox Code Playgroud)

所以是的,largeSize(largeSizes因为它是一个集合而应该被命名)是类型的EnumSet.它也应该是一般化的,因此被宣布为

EnumSet<Size> largeSizes
Run Code Online (Sandbox Code Playgroud)

这意味着什么,是largeSizes类型EnumSet.一个EnumSet是一个Set包含一个特定的枚举类型的枚举例如,在比其他更有效的方式Set实现(如HashSet,TreeSet等).要了解它EnumSet是什么,请阅读其API.

  • `大小`不应该是'大小`.XL是一个`Size`,而不是`Sizes`.`大小`不是**对象.这是一堂课.`Size.XL`是类`Size`的6个实例之一.根据定义,枚举是仅具有固定数量的实例的类(在本例中为S,M,...... XXXL).您无法创建枚举的新实例,否则它将不再是枚举.`大小`**是**一类.所有枚举都是类,但以不同的方式定义. (8认同)
  • 不,这是一组枚举值.`largeSizes`是一个包含XL,XXL和XXXL的集合.您可以用HashSet替换它,除了性能和内存消耗之外它不会改变任何东西.`大小`不是一个对象.这是一堂课.这个类定义了几个常量:L,XL,XXL等类型`Size`. (3认同)

Pet*_*rey 38

简化您的代码

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

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

L XL XXL XXXL
Run Code Online (Sandbox Code Playgroud)

如果您想了解更多细节,我建议您阅读本课程的来源.


Gáb*_*bor 38

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

EnumSet当您需要变量同时承担多个Enum值时,将使用An .例如,您写入屏幕的字体可以同时为粗体斜体.一个EnumSet将允许您添加不同的价值观,并测试其中的一个是否被实际设置在任何给定的时间.如果您从其他编程语言来到Java,这通常称为标志.

比较两者:

enum Size { S, M, L, XL, XXL, XXXL }
Size currentSize;
...
currentSize = Size.S;
...
if (currentSize == Size.S) ...
Run Code Online (Sandbox Code Playgroud)

定义,分配然后检查单个Enum值.

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

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


sha*_*ing 14

从约书亚布洛赫的书本身和他自己的话:

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){}

}
Run Code Online (Sandbox Code Playgroud)

客户端代码调用它可能会做类似的事情

SizeSet largeSizeSet = new SizeSet();
largeSizeSet.applySize(EnumSet.of(Size.L, Size.XXL, Size.XXL));
Run Code Online (Sandbox Code Playgroud)

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


小智 7

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

for (Day d : EnumSet.range(Day.MONDAY, Day.FRIDAY))
        System.out.println(d);
Run Code Online (Sandbox Code Playgroud)

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


jet*_*ton 5

根据Oracle文档

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

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