Guide de EnumSet

Guide de EnumSet

1. introduction

Dans ce tutoriel, nous allons explorer la collectionEnumSet du packagejava.util et discuter de ses particularités.

Nous allons d'abord montrer les principales caractéristiques de la collection, puis nous passerons en revue les éléments internes de la classe afin de comprendre ses avantages.

Enfin, nous allons couvrir les principales opérations qu'il fournit et mettre en œuvre quelques exemples de base.

2. Qu'est-ce qu'unEnumSet

An EnumSet is a specialized Set collection to work with enum classes. Il implémente l'interfaceSet et s'étend à partir deAbstractSet:

image

Même siAbstractSet etAbstractCollection fournissent des implémentations pour presque toutes les méthodes des interfacesSet etCollection,EnumSet remplace la plupart d'entre elles.

Lorsque nous prévoyons d'utiliser unEnumSet, nous devons prendre en considération certains points importants:

  • It can contain only enum values et toutes les valeurs doivent appartenir aux mêmesenum

  • It doesn’t allow to add null values, lançant unNullPointerException pour tenter de le faire

  • It’s not thread-safe, nous devons donc le synchroniser en externe si nécessaire

  • Les éléments sont stockés dans l'ordre dans lequel ils sont déclarés dans lesenum

  • It uses a fail-safe iterator qui fonctionne sur une copie, donc il ne lancera pas deConcurrentModificationException si la collection est modifiée lors de l'itération dessus

3. Pourquoi utiliserEnumSet

En règle générale,EnumSet should always be preferred over any other Set implementation when we are storing enum values.

Dans les sections suivantes, nous verrons ce qui rend cette collection meilleure que d'autres. Pour ce faire, nous allons brièvement montrer les éléments internes de la classe pour obtenir une meilleure compréhension.

3.1. Détails d'implémentation

EnumSet est une classepublicabstract qui contient plusieurs méthodes de fabrique statiques qui nous permettent de créer des instances. Le JDK fournit 2 implémentations différentes - sontpackage-private et soutenues par un vecteur de bits:

  • RegularEnumSet et

  • JumboEnumSet

RegularEnumSet uses a single long to represent the bit vector. Chaque bit de l'élémentlong représente une valeur desenum. La i-ème valeur de l'énumération sera stockée dans le i-ème bit, il est donc assez facile de savoir si une valeur est présente ou non. Since long is a 64-bit data type, this implementation can store up to 64 elements.

D'un autre côté,JumboEnumSet uses an array of long elements as a bit vector.This lets this implementation store more than 64 elements. Cela fonctionne à peu près comme lesRegularEnumSet mais en effectuant des calculs supplémentaires pour trouver l'index du tableau où la valeur est stockée.

Sans surprise, le premier élément long du tableau stockera les 64 premières valeurs desenum, le deuxième élément les 64 suivants, et ainsi de suite.

Les méthodes de fabriqueEnumSet créent des instances d'une implémentation ou d'une autre en fonction du nombre d'éléments desenum:

if (universe.length <= 64)
    return new RegularEnumSet<>(elementType, universe);
else
    return new JumboEnumSet<>(elementType, universe);

Gardez à l'esprit qu'il ne prend en compte que la taille de la classeenum, pas le nombre d'éléments qui seront stockés dans la collection.

3.2. Avantages de l'utilisation d'unEnumSet

En raison de l'implémentation d'unEnumSet que nous avons décrit ci-dessus,all the methods in an EnumSet are implemented using arithmetic bitwise operations. Ces calculs sont très rapides et donc toutes les opérations de base sont exécutées en temps constant.

Si nous comparonsEnumSet avec d'autres implémentations deSet commeHashSet, la première 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 leshashcode pour trouver le bon bucket.

De plus, en raison de la nature des vecteurs binaires, unEnumSet est très compact et efficace. Par conséquent, il utilise moins de mémoire, avec tous les avantages qu'il apporte.

4. Opérations principales

La majorité des méthodes d'unEnumSet fonctionnent comme n'importe quel autreSet, à l'exception des méthodes de création d'instances.

Dans les sections suivantes, nous montrerons en détail toutes les méthodes de création et nous couvrirons brièvement le reste des méthodes.

Dans nos exemples, nous allons travailler avec unColorenum:

public enum Color {
    RED, YELLOW, GREEN, BLUE, BLACK, WHITE
}

4.1. Méthodes de création

The most simple methods to create an EnumSet are allOf() and noneOf(). De cette façon, nous pouvons facilement créer unEnumSet contenant tous les éléments de notre énumérationColor:

EnumSet.allOf(Color.class);

De même, nous pouvons utilisernoneOf() pour faire le contraire et créer une collection vide deColor:

EnumSet.noneOf(Color.class);

If we want to create an EnumSet with a subset of the enum elements we can use the overloaded of() methods. Il est important de faire la différence entre les méthodes avec un nombre fixe de paramètres jusqu'à 5 différents et celle qui utilisevarargs:

image

Le Javadoc indique que les performances de la versionvarargs peuvent être plus lentes que les autres en raison de la création du tableau. Par conséquent, nous ne devrions l'utiliser que si nous devons initialement ajouter plus de 5 éléments.

Une autre façon de créer un sous-ensemble d'unenum consiste à utiliser la méthoderange():

EnumSet.range(Color.YELLOW, Color.BLUE);

Dans l'exemple ci-dessus, leEnumSet contient tous les éléments deYellow àBlue. Ils suivent l'ordre défini dans leenum:

[YELLOW, GREEN, BLUE]

Notez qu'il inclut à la fois les premier et dernier éléments spécifiés.

Another useful factory method is the complementOf() that allows us to exclude the elements passed as parameters. Créons unEnumSet avec tous les élémentsColor sauf le noir et blanc:

EnumSet.complementOf(EnumSet.of(Color.BLACK, Color.WHITE));

Si nous imprimons cette collection, nous pouvons voir qu'elle contient tous les autres éléments:

[RED, YELLOW, GREEN, BLUE]

Enfin,we can create an EnumSet by copying all the elements from another EnumSet:

EnumSet.copyOf(EnumSet.of(Color.BLACK, Color.WHITE));

En interne, il appelle la méthodeclone.

De plus,we can also copy all the elements from any Collection that contains enum elements. Utilisons-le pour copier tous les éléments d’une liste:

List colorsList = new ArrayList<>();
colorsList.add(Color.RED);
EnumSet listCopy = EnumSet.copyOf(colorsList);

Dans ce cas, lelistCopy contient uniquement la couleur rouge.

4.2. Autres opérations

Le reste des opérations fonctionne exactement de la même manière que toute autre implémentation deSet et il n'y a aucune différence dans la façon de les utiliser.

Par conséquent, nous pouvons facilement créer unEnumSet vide et ajouter quelques éléments:

EnumSet set = EnumSet.noneOf(Color.class);
set.add(Color.RED);
set.add(Color.YELLOW)

Vérifiez si la collection contient un élément spécifique:

set.contains(Color.RED);

Itérer sur les éléments:

set.forEach(System.out::println);

Ou simplement supprimer des éléments:

set.remove(Color.RED);

Ceci, bien sûr, parmi toutes les autres opérations prises en charge par unSet.

5. Conclusion

Dans cet article, nous avons montré les principales fonctionnalités deEnumSet, sa mise en œuvre interne et les avantages de son utilisation.

Nous avons également couvert les principales méthodes qu'il propose et mis en œuvre des exemples pour montrer comment nous pouvons les utiliser.

Comme toujours, le code source complet des exemples est disponibleover on GitHub.