Java Set conserver l'ordre?


179

Un ensemble Java conserve-t-il l'ordre? Une méthode me renvoie un ensemble et, supposément, les données sont ordonnées mais en itération sur l'ensemble, les données ne sont pas ordonnées. Y a-t-il une meilleure façon de gérer cela? La méthode doit-elle être modifiée pour renvoyer autre chose qu'un ensemble?


3
"Les éléments sont renvoyés sans ordre particulier (sauf si cet ensemble est une instance d'une classe qui fournit une garantie)." est ce que dit la méthode itératrice pour un ensemble. trouvé ici
keyer

Réponses:


257

L' Setinterface ne fournit aucune garantie de commande.

Sa sous-interface SortedSetreprésente un ensemble qui est trié selon un critère. Dans Java 6, il existe deux conteneurs standard qui implémentent SortedSet. Ils sont TreeSetet ConcurrentSkipListSet.

En plus de l' SortedSetinterface, il y a aussi la LinkedHashSetclasse. Il se souvient de l'ordre dans lequel les éléments ont été insérés dans l'ensemble et renvoie ses éléments dans cet ordre.


21
De plus, en raison du hachage de chaîne différent dans Java 8, l'ordre par défaut (non trié) dans les ensembles et les cartes changera. Si vous comptez sur une commande non triée, votre code se comportera différemment sous Java 8.
rustyx

Je comprends que la classe qui ne commande pas est normal, mais le comportement auquel je m'attendais était de les laisser comme ils ont été introduits et de ne pas gâcher l'ordre, au lieu de cela, il s'agit simplement de mélanger les éléments à chaque fois qu'ils sont agrégés. Votre solution n'est pas optimale car alors je
devrai

@White_King: Un ensemble est un concept mathématique qui ne contient pas la notion d '"ordre d'insertion", il est donc logique que l'interface Java suive ses conventions. Il existe des ensembles ordonnés mais l'ordre est spécifié par une relation (comparateur en Java), qui correspond à nouveau à la définition en théorie des ensembles avec la définition en Java. Votre attente de conserver l'ordre d'insertion vient probablement des listes, mais les ensembles ne sont pas des listes.
Konrad Höffner

103

LinkedHashSet est ce dont vous avez besoin.


43
A Listn'est pas un Set(il ne garantit pas l'unicité de l'appartenance).
Expiation limitée le

10
Dans de nombreux cas commerciaux uniques, List ne peut pas être utilisé uniquement pour conserver l'ordre au lieu de Set. LinkedHashSet maintient l'ordre et les magasins uniques.
gubs le

18

Comme beaucoup de membres l'ont suggéré, utilisez LinkedHashSet pour conserver l'ordre de la collection. Vous pouvez envelopper votre ensemble en utilisant cette implémentation.

L' implémentation de SortedSet peut être utilisée pour l'ordre trié, mais à vos fins, utilisez LinkedHashSet .

Également à partir de la documentation,

"Cette implémentation évite à ses clients la commande non spécifiée et généralement chaotique fournie par HashSet, sans entraîner le coût accru associé à TreeSet. Elle peut être utilisée pour produire une copie d'un ensemble qui a le même ordre que l'original, quel que soit l'original implémentation de l'ensemble: "

Source: http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashSet.html


9

L'ensemble n'est qu'une interface. Afin de conserver l'ordre, vous devez utiliser une implémentation spécifique de cette interface et de la sous-interface SortedSet, par exemple TreeSet ou LinkedHashSet. Vous pouvez envelopper votre ensemble de cette façon:

Set myOrderedSet = new LinkedHashSet(mySet);

7

Voici un résumé rapide des caractéristiques d'ordre des Setimplémentations standard disponibles en Java:

  1. conserver l'ordre d'insertion: LinkedHashSet et CopyOnWriteArraySet (thread-safe)
  2. garder les éléments triés dans l'ensemble: TreeSet , EnumSet (spécifique aux enums) et ConcurrentSkipListSet (thread-safe)
  3. ne conserve pas les éléments dans un ordre spécifique: HashSet (celui que vous avez essayé)

Pour votre cas spécifique, vous pouvez d'abord trier les éléments, puis utiliser l'un des 1 ou 2 (très probablement LinkedHashSetou TreeSet). Ou encore et plus efficacement , vous pouvez simplement ajouter des données non triées à un TreeSetqui se chargera du tri automatiquement pour vous.


7

Pour conserver la commande, utilisez Listou a LinkedHashSet.


1
Il est LinkedHashSet, non ... Map.
Marko Topolnik

J'ai besoin d'un ensemble pas d'une liste, j'ai besoin d'un ensemble qui conserve ÉGALEMENT l'ordre d'injection des objets je suppose
White_King

5

Un LinkedHashSet est une version ordonnée de HashSet qui maintient une liste doublement liée à travers tous les éléments. Utilisez cette classe au lieu de HashSet lorsque vous vous souciez de l'ordre d'itération.


3

Depuis le javadoc pour Set.iterator():

Renvoie un itérateur sur les éléments de cet ensemble. Les éléments sont retournés sans ordre particulier (sauf si cet ensemble est une instance d'une classe qui fournit une garantie).

Et, comme déjà indiqué par shuuchan , a TreeSetest une implémentation deSet qui a un ordre garanti:

Les éléments sont classés en utilisant leur ordre naturel, ou par un comparateur fourni au moment de la création de l'ensemble, en fonction du constructeur utilisé.


3

Normalement, set ne garde pas l'ordre, tel que HashSet afin de trouver rapidement un emelent, mais vous pouvez essayer LinkedHashSet il conservera l'ordre que vous avez mis.


1

Il y a 2 choses différentes.

  1. Triez les éléments dans un ensemble. Pour lequel nous avons SortedSet et des implémentations similaires.
  2. Maintenez l'ordre d'insertion dans un ensemble. Pour quels LinkedHashSet et CopyOnWriteArraySet (thread-safe) peuvent être utilisés.



-2

Seul SortedSetpeut faire la commande duSet


La question est de conserver l'ordre d'insertion (qui se trouve être trié).
assylias
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.