I looked under the hood for EnumSet.allOf
and it looks very efficient, especially for enums with less than 64 values.
Basically all sets share the single array of all possible enum values and the only other piece of information is a bitmask which in case of allOf
is set in one swoop.
On the other hand Enum.values() seems to be a bit of black magic. Moreover it returns an array, not a collection, so in many cases it must be decorated with Arrays.asList( ) to be usable in any place that expects collection.
So, should EnumSet.allOf
be more preferable to Enum.values
?
More specifically, which form of for
iterator should be used:
for ( final MyEnum val: MyEnum.values( ) );
or
for ( final MyEnum val: EnumSet.allOf( MyEnum.class ) );
Enums are used to hold state and are commonly compared, and enum comparisons are incredibly fast. Much, much faster than comparing strings.
Enums will usually use 4 bytes - their underlying type defaults to int unless you explicitly declare otherwise. The "greatly outperform" part depends largely on what you're doing with the enum once you get it. If you use it in a switch statement, enums will be faster.
Enums are crucial part of every application larger than “Hello World“. We use them everywhere. They are actually very useful: they restrict the input, allow you to compare the values by the reference, provide compile-time checks, and make the code easier to read.
The EnumSet is one of the specialized implementations of the Set interface for use with the enumeration type. A few important features of EnumSet are as follows: It extends AbstractSet class and implements Set Interface in Java. EnumSet class is a member of the Java Collections Framework & is not synchronized.
Because I did not receive the answer to my question on which one is more efficient, I've decided to do some testing of my own.
I've tested iteration over values()
, Arrays.asList( values() )
and EnumSet.allOf( )
. I've repeated these tests 10,000,000 times for different enum sizes. Here are the test results:
oneValueEnum_testValues 1.328 oneValueEnum_testList 1.687 oneValueEnum_testEnumSet 0.578 TwoValuesEnum_testValues 1.360 TwoValuesEnum_testList 1.906 TwoValuesEnum_testEnumSet 0.797 ThreeValuesEnum_testValues 1.343 ThreeValuesEnum_testList 2.141 ThreeValuesEnum_testEnumSet 1.000 FourValuesEnum_testValues 1.375 FourValuesEnum_testList 2.359 FourValuesEnum_testEnumSet 1.219 TenValuesEnum_testValues 1.453 TenValuesEnum_testList 3.531 TenValuesEnum_testEnumSet 2.485 TwentyValuesEnum_testValues 1.656 TwentyValuesEnum_testList 5.578 TwentyValuesEnum_testEnumSet 4.750 FortyValuesEnum_testValues 2.016 FortyValuesEnum_testList 9.703 FortyValuesEnum_testEnumSet 9.266
These are results for tests ran from command line. When I ran these tests from Eclipse, I got overwhelming support for testValues
. Basically it was smaller than EnumSet
even for small enums. I believe that the performance gain comes from optimization of array iterator in for ( val : array )
loop.
On the other hand, as soon as you need a java.util.Collection to pass around, Arrays.asList( )
looses over to EnumSet.allOf
, especially for small enums, which I believe will be a majority in any given codebase.
So, I would say you should use
for ( final MyEnum val: MyEnum.values( ) )
but
Iterables.filter( EnumSet.allOf( MyEnum.class ), new Predicate< MyEnum >( ) {...} )
And only use Arrays.asList( MyEnum.values( ) )
where java.util.List
is absolutely required.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With