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 a 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 ) );
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.