60 votes

Enum.values () vs EnumSet.allOf (). Lequel est le plus préférable?

J'ai regardé sous le capot pour EnumSet.allOf et il a l'air très efficace, en particulier pour les énumérations avec moins de 64 valeurs.

Fondamentalement, tous les ensembles de partager le seul tableau de toutes les valeurs de l'enum et le seul autre élément d'information est un masque de bits qui, en cas d' allOf est définie en un seul coup.

D'autre part Enum.les valeurs de() semble être un peu de la magie noire. En outre, elle retourne un tableau, pas une collection, de sorte que dans de nombreux cas, il doit être décoré avec des Tableaux.asList( ) pour être utilisable dans n'importe quel endroit qui attend de collection.

Alors, faut - EnumSet.allOf être plus préférable d' Enum.values?

Plus précisément, la forme d' for itérateur doit être utilisée:

for ( final MyEnum val: MyEnum.values( ) );

ou

for ( final MyEnum val: EnumSet.allOf( MyEnum.class ) );

92voto

Alexander Pogrebnyak Points 24964

Parce que je n'ai pas reçu la réponse à ma question sur laquelle est la plus efficace, j'ai décidé de faire quelques tests de mon propre.

J'ai testé une itération sur values(), Arrays.asList( values() ) et EnumSet.allOf( ). J'ai répété ces tests de 10 000 000 de fois pour différents enum tailles. Voici les résultats du test:

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

Ce sont les résultats de tests a couru à partir de la ligne de commande. Quand j'ai couru ces tests à partir d'Eclipse, j'ai reçu un énorme soutien testValues. Fondamentalement, il était plus petit que EnumSet , même pour les petits les énumérations. Je crois que le gain de performance vient de l'optimisation de la matrice de itérateur en for ( val : array ) boucle.

En revanche, dès que vous avez besoin de java.util.Collection de passer autour, Arrays.asList( ) perd plus d' EnumSet.allOf, surtout pour les petits les énumérations, qui sera, je le crois une majorité dans aucune donnée de la base de code.

Je dirais donc, vous devez utiliser

for ( final MyEnum val: MyEnum.values( ) )

mais

Iterables.filter(
    EnumSet.allOf( MyEnum.class ),
    new Predicate< MyEnum >( ) {...}
)

Et de n'utiliser Arrays.asList( MyEnum.values( ) )java.util.List est absolument nécessaire.

12voto

Peter Lawrey Points 229686

Vous devriez utiliser l'approche qui est la plus simple et la plus claire pour vous. La performance ne devrait pas être prise en compte dans la plupart des situations.

IMHO: aucune option ne fonctionne très bien car ils créent tous deux des objets. Un dans le premier cas et trois dans le second. Vous pouvez construire une constante contenant toutes les valeurs pour des raisons de performances.

7voto

irreputable Points 25577

Il y a aussi Class.getEnumConstants()

sous le capot, ils appellent tous values() méthodes de types énumérés de toute façon, par réflexion .

4voto

Arne Burmeister Points 8423

La méthode values() est plus claire et plus performante si vous souhaitez simplement itérer sur toutes les valeurs enum possibles. Les valeurs sont mises en cache par la classe (voir Class.getEnumConstants() )

Si vous avez besoin d'un sous-ensemble de valeurs, vous devez utiliser un EnumSet . Commencez avec allOf() ou noneOf() et ajoutez ou supprimez des valeurs ou utilisez simplement of() selon vos besoins.

2voto

Enno Shioji Points 12298

Non pas que je suis passé par l'ensemble de la mise en œuvre, mais il me semble que EnumSet.allOf() est fondamentalement en utilisant la même infrastructure .les valeurs de(). Donc, je m'attends à EnumSet.allOf() nécessite certains (probablement négligeable) des mesures supplémentaires (voir http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6276988).

Il me semble clair que l'utilisation de foreach est - for(MyEnum val : MyEnum.values()) pourquoi faire autrement? Vous ne confondez l'entretien programmeur.

Je veux dire, si vous avez besoin d'une collection, vous devez en obtenir un. Si vous souhaitez utiliser un foreach, les tableaux sont assez bonnes. J'irais même jusqu'à préférer les tableaux si pressé! Pourquoi envelopper tout avec rien, si ce que vous avez obtenu (tableau) est assez bon? Les choses simples sont normalement plus rapide.

De toute façon, Peter Lawrey est droit. Ne vous préoccupez pas de l'exécution de cette.. Il est assez rapide, et les chances sont qu'il ya des millions d'autres goulots d'étranglement qui rendent ce petit théorique différence de performances comme totalement hors de propos (Ne pas voir sa "création d'un objet" point de si. Pour moi le premier exemple semble être 100% OK).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X