Java Set retener el orden?

179

¿Un Java Set retiene el orden? Un método me devuelve un Set y supuestamente los datos están ordenados pero iterando sobre el Set, los datos están desordenados. ¿Hay una mejor manera de manejar esto? ¿Es necesario cambiar el método para devolver algo distinto de un conjunto?

usuario840930
fuente
3
"Los elementos se devuelven en ningún orden en particular (a menos que este conjunto sea una instancia de alguna clase que proporcione una garantía)". es lo que dice el método iterador para un conjunto. encontrado aquí
keyser

Respuestas:

256

La Setinterfaz no ofrece ninguna garantía de pedido.

Su subinterfaz SortedSetrepresenta un conjunto que se ordena según algún criterio. En Java 6, hay dos contenedores estándar que se implementan SortedSet. Son TreeSety ConcurrentSkipListSet.

Además de la SortedSetinterfaz, también está la LinkedHashSetclase. Recuerda el orden en que se insertaron los elementos en el conjunto y devuelve sus elementos en ese orden.

NPE
fuente
21
Además, debido al diferente hashing de cadenas en Java 8, el orden predeterminado (sin clasificar) en Conjuntos y mapas cambiará. Si confía en pedidos sin clasificar, su código se comportará de manera diferente en Java 8.
rustyx
Entiendo que la clase que no ordena es normal, pero el comportamiento que esperaba era dejarlos tal como fueron introducidos y no alterar el orden, sino que simplemente baraja los elementos cada vez que se agrega uno. Su solución no es óptima porque entonces tendré que implementar una estructura completa para que se ordenen DE LA MISMA FORMA en que se introdujeron: S
White_King
@White_King: un conjunto es un concepto matemático que no contiene la noción de "orden de inserción", por lo que tiene sentido que la interfaz Java siga sus convenciones. Hay conjuntos ordenados, pero el orden se especifica mediante una relación (comparador en Java), que nuevamente coincide con la definición en teoría de conjuntos con la definición en Java. Su expectativa de mantener el orden de inserción probablemente proviene de listas, pero los conjuntos no son listas.
Konrad Höffner el
103

LinkedHashSet es lo que necesitas.

xiaofeng.li
fuente
43
A Listno es un Set(no garantiza la unicidad de membresía).
Expiación limitada el
10
En muchos casos comerciales únicos, la Lista no se puede usar solo para retener el orden en lugar de Establecer. LinkedHashSet mantiene el orden y las tiendas son únicas.
Gubs
18

Como muchos de los miembros sugirieron usar LinkedHashSet para retener el orden de la colección. U puede envolver su conjunto utilizando esta implementación.

La implementación de SortedSet se puede usar para el orden ordenado, pero para su propósito use LinkedHashSet .

También de los documentos,

"Esta implementación ahorra a sus clientes el pedido no especificado, generalmente caótico, proporcionado por HashSet, sin incurrir en el mayor costo asociado con TreeSet. Se puede utilizar para producir una copia de un conjunto que tenga el mismo orden que el original, independientemente del original. implementación del conjunto: "

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

Lakshman
fuente
9

Set es solo una interfaz. Para retener el orden, debe usar una implementación específica de esa interfaz y la subinterfaz SortedSet, por ejemplo TreeSet o LinkedHashSet. Puedes envolver tu Set de esta manera:

Set myOrderedSet = new LinkedHashSet(mySet);
javatutorial
fuente
7

Aquí hay un resumen rápido de las características de orden de las Setimplementaciones estándar disponibles en Java:

  1. mantenga el orden de inserción: LinkedHashSet y CopyOnWriteArraySet (seguro para subprocesos)
  2. mantenga los elementos ordenados dentro del conjunto: TreeSet , EnumSet (específico para las enumeraciones) y ConcurrentSkipListSet (seguro para subprocesos)
  3. no mantiene los elementos en ningún orden específico: HashSet (el que probó)

Para su caso específico, puede ordenar los elementos primero y luego usar cualquiera de 1 o 2 (muy probablemente LinkedHashSeto TreeSet). O de manera alternativa y más eficiente , simplemente puede agregar datos sin clasificar a un TreeSetque se encargará de la clasificación automáticamente por usted.

asilias
fuente
7

Para retener la orden use Listo a LinkedHashSet.

JHS
fuente
1
Es LinkedHashSet, no ... Map.
Marko Topolnik
Necesito un conjunto no es una lista, necesito un conjunto que conserva también el orden de inyección de los objetos supongo
White_King
5

LinkedHashSet es una versión ordenada de HashSet que mantiene una lista doblemente vinculada en todos los elementos. Use esta clase en lugar de HashSet cuando le importe el orden de iteración.

Danail Tsvetanov
fuente
3

Del javadoc para Set.iterator():

Devuelve un iterador sobre los elementos de este conjunto. Los elementos se devuelven en ningún orden en particular (a menos que este conjunto sea una instancia de alguna clase que proporcione una garantía).

Y, como ya dijo shuuchan , a TreeSetes una implementación Setque tiene un orden garantizado:

Los elementos se ordenan utilizando su ordenamiento natural o mediante un comparador proporcionado en el momento de creación establecido, según el constructor utilizado.

hmjd
fuente
3

Normalmente, set no mantiene el orden, como HashSet para encontrar rápidamente un emelent, pero puede probar LinkedHashSet, mantendrá el orden que ingresó.

usuario1335794
fuente
1

Hay 2 cosas diferentes.

  1. Ordenar los elementos en un conjunto. Para lo cual tenemos SortedSet e implementaciones similares.
  2. Mantener el orden de inserción en un conjunto. Para lo cual se pueden usar LinkedHashSet y CopyOnWriteArraySet (seguro para subprocesos).
Aruna
fuente
0

La interfaz Set en sí no estipula ningún orden en particular. El SortedSet hace sin embargo.

Jens Borgland
fuente
-2

Solo se SortedSetpuede ordenar elSet


fuente
La pregunta se trata de retener el orden de inserción (que está ordenado).
Assylias