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创build了Enumtypes的Sizes。

我的问题是: largeSize是EnumSettypes的一个对象? 这是什么意思? 我真的想更好地理解它。

至于任何variables,其types可以在其声明中find:

 EnumSet largeSize 

所以是的, largeSize (应该命名为largeSizes因为它是一个集合)是EnumSettypes的。 它也应该被基因化,因此被宣布为

 EnumSet<Size> largeSizes 

这意味着, largeSizes的types是EnumSetEnumSet是一个包含特定枚举types的枚举实例的Set ,比其他Set实现(如HashSetTreeSet等)更有效。 要知道EnumSet是什么,请阅读它的API 。

简化你的代码

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

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

 L XL XXL XXXL 

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

一个简单的Enum值是一次只能select一个值的列表。 使用你的例子,一个尺寸可以只是S,M,L等等之一。 你可以使用简单的常量而不是Enum但是这样做有可读性,易维护和严格types检查的优点。

当需要一个variables同时假定多个Enum值时,将使用EnumSet 。 例如,您写入的字体可以同时为粗体斜体EnumSet将允许您添加各种值,并testing是否在给定时间内实际设置了其中一个值。 如果你从其他编程语言来到Java,这是通常称为标志的function。

比较两者:

 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专门用于存储枚举types元素并快速迭代它。 例如。

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

以上片段将显示星期一至星期五的星期几。

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

java.util包提供了EnumSet类来高效地表示从单个枚举types中绘制的值集合。 这个类实现了Set接口,提供了所有其他Set实现的丰富性,types安全性和互操作性。 但是在内部,每个EnumSet被表示为一个位向量。 如果底层的枚举types有64个或更less的元素,而且大多数都是这样,那么整个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传递给方法,但接受接口而不是具体实现是一个好习惯。

给出以下示例:

 .... 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实现,与枚举types一起使用并进行了优化,就这些了。

 EnumSet largeSize 

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

 Size 

大小是具有常数值S,M,L,XL,XXL,XXXL的一类Enumtypes。

 largeSize.iterator() 

EnumSet的迭代器按自然顺序排列,最初声明枚举值的顺序。

  • EnumSet类是Java集合框架的成员,并未同步。
  • 它是一个高性能的集合实现,它们比HashSet快得多。
  • 每个EnumSet实例的所有元素必须是单个枚举types的元素。

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

根据Oracle文档

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

可读,types安全,内存占用less…你还需要什么?

它迅速将任何枚举元素变成一个集合,枚举集合又是另一种types的集合。

 public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH } EnumSet.of(Style.BOLD, Style.ITALIC);