Enum.values() vs EnumSet.allOf( ). Which one is more preferable?
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.
You should use the approach which is simplest and clearest to you. Performance shouldn't be a consideration in most situations.
IMHO: neither option performs very well as they both create objects. One in the first case and three in the second. You could construct a constant which holds all the values for performance reasons.
There is also Class.getEnumConstants()
under the hood they all call values()
methods of enum types anyway, through reflection.