Set
modèlise un ensemble d'objets dans lequel on ne peut pas trouver de doublons. Cette notion impose que l'égalité entre objets soit définie, ce qui est le cas, puisque tout objet Java dispose d'une méthode
equals()
.
À la différence des interfaces
List
et
Collection
, l'ajout d'un élément dans un
Set
peut donc échouer, si cet élément s'y trouve déjà. C'est la raison pour laquelle la méthode
add(T t)
retourne un booléen. Ce booléen est toujours à
true
dans une collection ou une liste, dans le cas des
Set
il arrive qu'il soit à
false
.
Enfin notons qu'un
Set
ne peut pas contenir plus d'un objet nul. Certaines implémentations empêchent l'ajout d'objets nuls dans un
Set
.
L'implémentation fournie par l'API Java,
HashSet
, utilise, pour des raisons de performances, les codes de hachage des objets ajoutés. Cela est légal, puisque deux objets égaux doivent avoir même code de hachage. Respecter ce contrat s'avère donc crucial ici : s'il ne l'est pas, le
HashSet
ne pourra pas fonctionner correctement. De plus, on prendra garde que les champs utilisés pour la construction du code de hachage, et pour la méthode
equals()
, ne sont pas modifiés une fois l'objet ajouté à un
HashSet
. Effectivement, le
HashSet
ne pourrait pas détecter ces modifications, et ne mettra pas à jour le code de hachage qu'il utilise en interne. Là encore le fonctionnement du
HashSet
sera perturbé.
HashSet
et
LinkedHashSet
.
equals()
et
hashCode()
des objets ajoutés à un
HashSet
respectent leur contrat.
Cette implémentation offre des performances constantes pour les opérations
add(T t)
,
remove(T t)
,
contains(T t)
et
size()
. Le temps pris par ces opérations n'augmente donc pas avec le cardinal du
HashSet
. L'itération sur les éléments d'un
HashSet
est, elle, proportionnel à ce cardinal, et à la capacité totale du
HashSet
. On veillera donc à ne pas itérer sur de tels ensembles s'ils contiennent beaucoup d'éléments.
Notons que l'itération sur les éléments d'un
HashSet
se fait dans un ordre qui n'est pas prévisible, tout comme pour une collection classique.
LinkedHashSet
est une extension de
HashSet
. Elle offre donc les mêmes fonctionnalités et la même sémantique.
Cette classe entretient de plus une double liste chaînée dont les éléments sont les entrées de la table de hachage qui stocke les objets. Cela permet de conserver l'ordre dans lequel on parcourt les objets lors d'une itération. Le fait d'ajouter à un
LinkedHashSet
un objet qui s'y trouve déjà ne change pas la place de cet objet dans l'ensemble.
L'entretien de cette double liste est une surcharge mineure, qui n'affecte que très peu les opérations
add(T t)
,
remove(T t)
,
contains(T t)
et
size()
. En revanche, itérer ne dépend pas de la capacité de cette table, uniquement de son cardinal.
Set
.
Exemple 8. Utilisation d'un
Set
// dans une méthode main // création du set Set<String> set = new HashSet<String>() ; // ajout d'élément System.out.println("J'ajoute un : " + set.add("un")) ; System.out.println("J'ajoute deux : " + set.add("deux")) ; // ajout d'un doublon : échec System.out.println("J'ajoute encore un : " + set.add("un")) ; // affichage de la taille du set System.out.println("Taille du set : " + set.size()) ;
J'ajoute un : true J'ajoute deux : true J'ajoute encore un : false Taille du set : 2