Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enum.values() vs EnumSet.allOf( ). Which one is more preferable?

Tags:

java

enums

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 ) ); 
like image 804
Alexander Pogrebnyak Avatar asked Mar 17 '10 18:03

Alexander Pogrebnyak


People also ask

Are enums faster than strings?

Enums are used to hold state and are commonly compared, and enum comparisons are incredibly fast. Much, much faster than comparing strings.

Why is enum faster?

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.

Is enum efficient?

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.

What is the use of EnumSet?

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.


1 Answers

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.

like image 53
Alexander Pogrebnyak Avatar answered Oct 13 '22 00:10

Alexander Pogrebnyak