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?

user840930
la source
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.

NPE
la source
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.

xiaofeng.li
la source
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

Lakshman
la source
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);
javatutoriel
la source
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.

assylies
la source
7

Pour conserver la commande, utilisez Listou a LinkedHashSet.

JHS
la source
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.

Danail Tsvetanov
la source
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é.

hmjd
la source
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.

user1335794
la source
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.
Aruna
la source
0

L'interface Set elle-même ne stipule aucun ordre particulier. Le SortedSet le fait cependant.

Jens Borgland
la source
-2

Seul SortedSetpeut faire la commande duSet


la source
La question est de conserver l'ordre d'insertion (qui se trouve être trié).
assylias