问题
I have the following example:
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;
}
In this code I can understand that the Enum creates an Enum type of Sizes.
My question is: is largeSize
an object of EnumSet type? What does it really mean? I really want to understand it better.
回答1:
As for any variable, its type is found in its declaration:
EnumSet largeSize
So yes, largeSize
(which should be named largeSizes
since it's a collection) is of type EnumSet
. It should also be generified, and thus be declared as
EnumSet<Size> largeSizes
What it means, is that largeSizes
is of type EnumSet
. An EnumSet
is a Set
which contains enum instance of a specific enum type, in a more efficient way than other Set
implementations (like HashSet
, TreeSet
, etc.). To know what an EnumSet
is, read its API.
回答2:
Simplifying your code
EnumSet<Size> largeSize = EnumSet.of(Size.XXXL, Size.XXL, Size.XL, Size.L);
for(Size size: largeSize)
System.out.print(size+" ");
You can see that largeSize is a regular Set except its designed to store Enums. How is that different? Firstly the JVM knows all the possible values of the set which means instead of storing all the objects it can use a bitmap where 1 means the item is present and 0 means it is not. This also means the order of the set is the order of the ordinal values i.e. the order they were defined. This is why this prints
L XL XXL XXXL
If you want to know more detail I suggest you read the source for this class.
回答3:
A simple Enum
is a list of values that you can only select one from at a time. Using your example, a size can be only one of S, M, L, etc for any given cloth. You could use simple constants instead of the Enum
but this has its advantages of readability, easier maintenance and strict type checking.
An EnumSet
will be used when you have the need for a variable to assume more than one Enum
value at the same time. For instance, a font you write to screen with can be both bold and italic at the same time. An EnumSet
will allow you to add the various values and to test whether one of those is actually set at any given time. If you have come to Java from other programming languages, this is the functionality usually called flags.
Compare the two:
enum Size { S, M, L, XL, XXL, XXXL }
Size currentSize;
...
currentSize = Size.S;
...
if (currentSize == Size.S) ...
defines, assigns and then checks for a single Enum
value.
enum FontStyle { Bold, Italic, Underline, Strikethrough }
EnumSet<FontStyle> currentStyle;
...
currentStyle = EnumSet.of(FontStyle.Bold, FontStyle.Italic);
...
if (currentStyle.contains(FontStyle.Italic)) ...
defines, assigns two Enum
values at the same time, then checks whether one of those is actually set or not.
回答4:
From Joshua Bloch's book itself and in his own word:
The java.util package provides EnumSet class to efficiently represent sets of values drawn from a single enum type. This class implements the Set interface, providing all of the richness, type safety and interoperability you get with any other Set implementation. But internally, each EnumSet is represented as a bit vector. If the underlying enum type has sixty-four or fewer elements -- and most do -- the entire EnumSet is represented with a single long, so its performance is comparable to that of a bit field. Bulk operations, such as removeAll and retainAll, are implemented using bit wise arithmetic, just as you'll do manually for bit fields. But you are insulated from the ugliness and error-proneness of manual bit twiddling. The EnumSet does the hard work for you.
So we can do something like this.
public class SizeSet {
public enum Size {S, M, L, XL, XXL, XXXL}
public void applySize(Set<Size> sizes){}
}
Client Code calling it might do something like
SizeSet largeSizeSet = new SizeSet();
largeSizeSet.applySize(EnumSet.of(Size.L, Size.XXL, Size.XXL));
Note that the applySize method takes the Set<Size>
rather than an EnumSet<Size>
. While it is pretty
obvious and likely that the client would pass an EnumSet to the method, it is a good practice to accept an interface rather than the concrete implementation.
回答5:
EnumSet is specifically used for storing the enum type element and iterating over it quickly. Eg.
for (Day d : EnumSet.range(Day.MONDAY, Day.FRIDAY))
System.out.println(d);
The above snippet will display the days of the week from Monday through Friday.
回答6:
According to Oracle doc
Enum sets are represented internally as bit vectors. This representation is extremely compact and efficient.
Readable, type safe, low memory footprint... What do you want more?
回答7:
Given the following example:
....
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);
so, what is sizeSet in the above example?
EnumSet is nothing different from the above example, only that EnumSet is a special Set implementation that works with and optimized with enum types, that's all.
回答8:
EnumSet largeSize
EnumSet largeSize is a set of Enum values which contains XL, XXL and XXXL.
Size
Size is a class of Enum type with constant values S, M, L, XL, XXL, XXXL.
largeSize.iterator()
The Iterator for EnumSet is in natural order, the order in which the values of the enum were originally declared.
- EnumSet class is a member of the Java Collections Framework & is not synchronized.
- Its a high performance set implementation, they are much faster than HashSet.
- All elements of each EnumSet instance must be elements of a single enum type.
To Know more read the api doc : http://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html
回答9:
An EnumSet
is a specialized Set collection to work with enum classes. It implements the Set
interface and extends from AbstractSet
:
When you plan to use an EnumSet youhave to take into consideration some points:
- It can contain only enum values and all the values have to belong to the same enum
- It doesn’t allow to add null values, throwing a NullPointerException in an attempt to do so
- It’s not thread-safe, so we need to synchronize it externally if required
- The elements are stored following the order in which they are declared in the enum
- It uses a fail-safe iterator that works on a copy, so it won’t throw a ConcurrentModificationException if the collection is modified when iterating over it
Now, the EnumSet largeSize
part is a variable declaration so yes, it's of type EnumSet. Please notice that you can add the type of elements in the collection for better type safety: EnumSet<Size>
Check out this article to learn more about EnumSet.
回答10:
It quickly turn any Enum elements into a set, EnumSet is yet another type of Set.
public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH }
EnumSet.of(Style.BOLD, Style.ITALIC);
来源:https://stackoverflow.com/questions/11825009/what-does-enumset-really-mean