J'ai l'exemple suivant:
import Java.util.EnumSet;
import Java.util.Iterator;
public class SizeSet {
public static void main(String[] args) {
EnumSet largeSize = EnumSet.of(Size.XL,Size.XXL,Size.XXXL);
for(Iterator it = largeSize.iterator();it.hasNext();){
Size size = (Size)it.next();
System.out.println(size);
}
}
}
enum Size {
S, M, L, XL, XXL, XXXL;
}
Dans ce code, je peux comprendre que l’énumération crée un type de tailles Enum.
Ma question est la suivante: largeSize
est-il un objet de type EnumSet? Qu'est-ce que cela signifie vraiment? Je veux vraiment mieux comprendre.
Comme pour toute variable, son type se trouve dans sa déclaration:
EnumSet largeSize
Donc oui, largeSize
(qui devrait être nommé largeSizes
puisqu'il s'agit d'une collection) est de type EnumSet
. Il devrait également être généralisé, et donc être déclaré comme
EnumSet<Size> largeSizes
Cela signifie que largeSizes
est de type EnumSet
. Un EnumSet
est un Set
qui contient une instance enum d'un type enum spécifique, de manière plus efficace que d'autres implémentations Set
(comme HashSet
, TreeSet
, etc.). Pour savoir ce qu’est un EnumSet
, lisez son API .
Simplifier votre code
EnumSet<Size> largeSize = EnumSet.of(Size.XXXL, Size.XXL, Size.XL, Size.L);
for(Size size: largeSize)
System.out.print(size+" ");
Vous pouvez voir que largeSize est un ensemble standard, sauf qu'il est conçu pour stocker des énumérations. En quoi est-ce différent? Premièrement, la machine virtuelle Java connaît toutes les valeurs possibles de l'ensemble, ce qui signifie qu'au lieu de stocker tous les objets, elle peut utiliser une image bitmap, où 1 signifie que l'élément est présent et 0 que ce n'est pas le cas. Cela signifie également que l'ordre de l'ensemble est l'ordre des valeurs ordinales, c'est-à-dire l'ordre dans lequel elles ont été définies. C'est pourquoi cela imprime
L XL XXL XXXL
Si vous voulez en savoir plus en détail, je vous suggère de lire la source de ce cours.
Un simple Enum
est une liste de valeurs que vous ne pouvez sélectionner qu’une à la fois. En utilisant votre exemple, une taille ne peut être que l'une des tailles S, M, L, etc. pour un tissu donné. Vous pouvez utiliser des constantes simples à la place de Enum
, mais cela présente des avantages de lisibilité, de maintenance simplifiée et de vérification de type stricte.
Un EnumSet
sera utilisé lorsque vous aurez besoin d'une variable pour assumer plus d'une valeur Enum
à la fois. Par exemple, une police avec laquelle vous écrivez à l'écran peut être à la fois en gras et en en italique en même temps. Un EnumSet
vous permettra d’ajouter les différentes valeurs et de vérifier si l’une d’elles est réellement définie à un moment donné. Si vous êtes arrivé à Java à partir d'autres langages de programmation, il s'agit de la fonctionnalité généralement appelée flags.
Comparez les deux:
enum Size { S, M, L, XL, XXL, XXXL }
Size currentSize;
...
currentSize = Size.S;
...
if (currentSize == Size.S) ...
définit, attribue puis recherche une seule valeur Enum
.
enum FontStyle { Bold, Italic, Underline, Strikethrough }
EnumSet<FontStyle> currentStyle;
...
currentStyle = EnumSet.of(FontStyle.Bold, FontStyle.Italic);
...
if (currentStyle.contains(FontStyle.Italic)) ...
définit, attribue deux valeurs Enum
en même temps, puis vérifie si l’une d’elles est définie ou non.
Du livre de Joshua Bloch lui-même et dans sa propre Parole:
Le package Java.util fournit la classe EnumSet pour représenter efficacement des ensembles de valeurs tirées d'un seul type enum. Cette classe implémente l’interface Set, fournissant toute la richesse, la sécurité de type et l’interopérabilité que vous obtenez avec toute autre implémentation de Set. Mais en interne, chaque EnumSet est représenté sous forme de vecteur de bits. Si le type enum sous-jacent comporte soixante-quatre éléments ou moins (et la plupart le font), l'ensemble EnumSet est représenté par un seul long; ses performances sont donc comparables à celles d'un champ de bits. Les opérations en bloc, telles que removeAll et rétentionAll, sont implémentées à l'aide de l'arithmétique par bits, comme vous le ferez manuellement pour les champs de bits. Mais vous êtes isolé de la laideur et de la prédisposition aux erreurs du jeu manuel. EnumSet fait le travail difficile pour vous.
Donc, nous pouvons faire quelque chose comme ça.
public class SizeSet {
public enum Size {S, M, L, XL, XXL, XXXL}
public void applySize(Set<Size> sizes){}
}
Code client appelant cela pourrait faire quelque chose comme
SizeSet largeSizeSet = new SizeSet();
largeSizeSet.applySize(EnumSet.of(Size.L, Size.XXL, Size.XXL));
Notez que la méthode applySize utilise le Set<Size>
Plutôt qu'un EnumSet<Size>
. Bien qu'il soit assez évident et probable que le client transmette un EnumSet à la méthode, il est recommandé d'accepter une interface plutôt qu'une implémentation concrète.
EnumSet est spécifiquement utilisé pour stocker l'élément de type enum et pour l'itérer rapidement. Par exemple.
for (Day d : EnumSet.range(Day.MONDAY, Day.FRIDAY))
System.out.println(d);
L'extrait ci-dessus affiche les jours de la semaine du lundi au vendredi.
Selon doc Oracle
Les ensembles d'énumération sont représentés de manière interne en tant que vecteurs de bits. Cette représentation est extrêmement compacte et efficace.
Lisible, tapez en toute sécurité, faible empreinte mémoire ... Que voulez-vous de plus?
Étant donné l'exemple suivant:
....
public static final String S = "s";
public static final String M = "m";
public static final String L = "l";
....
Set<String> sizeSet = new HashSet<String>();
sizeSet.add(S);
sizeSet.add(M);
oui, quel est sizeSet dans l'exemple ci-dessus?
EnumSet n'est pas différent de l'exemple ci-dessus, seulement qu'EnumSet est une implémentation Set spéciale qui fonctionne avec et optimise avec les types enum, c'est tout.
EnumSet largeSize
EnumSet largeSize est un ensemble de valeurs Enum qui contient XL, XXL et XXXL.
Size
La taille est une classe de type Enum avec les valeurs constantes S, M, L, XL, XXL, XXXL.
largeSize.iterator()
L'Iterator for EnumSet est dans l'ordre naturel, l'ordre dans lequel les valeurs de l'énum ont été déclarées à l'origine.
Pour en savoir plus, lisez le document api: http://docs.Oracle.com/javase/8/docs/api/Java/util/EnumSet.html
En règle générale, EnumSet
devrait toujours être préféré à toute autre implémentation de Set lorsque nous stockons des valeurs enum.
Avantages de l'utilisation d'un EnumSet
:
Les méthodes d'un EnumSet
sont implémentées à l'aide d'opérations arithmétiques au niveau des bits. Ces calculs étant très rapides, toutes les opérations de base sont exécutées dans un temps constant.
Si nous comparons EnumSet
avec d'autres implémentations de Set comme HashSet
, la première solution est généralement plus rapide, car les valeurs sont stockées dans un ordre prévisible et un seul bit doit être examiné pour chaque calcul. Contrairement à HashSet, il n’est pas nécessaire de calculer le hashcode pour trouver le bon compartiment.
De plus, en raison de la nature des vecteurs bits, un EnumSet
est très compact et efficace. Par conséquent, il utilise moins de mémoire, avec tous les avantages qu'il apporte.
les règles sonarsource disent :
Lorsque tous les éléments d'un ensemble sont des valeurs de la même énumération, cet ensemble peut être remplacé par un EnumSet, ce qui peut s'avérer beaucoup plus efficace que d'autres ensembles, car la structure de données sous-jacente est un bitmap simple.
La source est ici
Un EnumSet
est une collection spécialisée permettant de travailler avec des classes enum. Il implémente l'interface Set
et s'étend de AbstractSet
:
Lorsque vous envisagez d’utiliser un EnumSet, vous devez tenir compte de certains points:
Maintenant le EnumSet largeSize
partie est une déclaration de variable , donc oui, elle est de type EnumSet. Veuillez noter que vous pouvez ajouter le type d'éléments dans la collection pour une meilleure sécurité du type: EnumSet<Size>
Consultez cet article pour en savoir plus sur EnumSet .