O Java Set retém a ordem?

179

Um Java Set mantém a ordem? Um método está retornando um conjunto para mim e, supostamente, os dados são ordenados, mas iterando sobre o conjunto, os dados são desordenados. Existe uma maneira melhor de gerenciar isso? O método precisa ser alterado para retornar algo diferente de um conjunto?

user840930
fonte
3
"Os elementos são retornados em nenhuma ordem específica (a menos que este conjunto seja uma instância de alguma classe que forneça uma garantia)." é o que o método iterador de um conjunto diz. encontrado aqui
keyser 25/05

Respostas:

256

A Setinterface não fornece nenhuma garantia de pedido.

Sua subinterface SortedSetrepresenta um conjunto que é classificado de acordo com algum critério. No Java 6, existem dois contêineres padrão que implementam SortedSet. Eles são TreeSete ConcurrentSkipListSet.

Além da SortedSetinterface, há também a LinkedHashSetclasse Ele se lembra da ordem em que os elementos foram inseridos no conjunto e retorna seus elementos nessa ordem.

NPE
fonte
21
Além disso, devido ao diferente hash de String no Java 8, a ordem padrão (não classificada) em Sets e Maps será alterada. Se você confiar na ordenação não classificado, o seu código irá se comportar de maneira diferente em Java 8.
rustyx
Entendo que a classe que não está ordenando é normal, mas o comportamento que eu esperava era deixá-los como eles foram introduzidos e não mexer com o pedido; em vez disso, apenas embaralha os elementos cada vez que um é agregado. Sua solução não é ótima, porque então terei que implementar uma estrutura inteira para que sejam classificadas da mesma maneira que foram introduzidas: S
White_King
@White_King: Um conjunto é um conceito matemático que não contém a noção de "ordem de inserção"; portanto, faz sentido que a interface Java siga suas convenções. Existem conjuntos ordenados, mas o pedido é especificado por uma relação (comparador em Java), correspondendo novamente a definição na teoria de conjuntos à definição em Java. Sua expectativa de manter a ordem de inserção provavelmente vem de listas, mas os conjuntos não são listas.
Konrad Höffner
103

LinkedHashSet é o que você precisa.

xiaofeng.li
fonte
43
A Listnão é um Set(não garante a exclusividade da associação).
Expiação limitada
10
Em muitos casos exclusivos de negócios, a Lista não pode ser usada apenas para manter o pedido em vez de Definir. LinkedHashSet mantém o pedido e armazena exclusivos.
gubs 9/07/2015
18

Como muitos dos membros sugeriram, use o LinkedHashSet para manter a ordem da coleção. Você pode agrupar seu conjunto usando esta implementação.

A implementação SortedSet pode ser usada para ordem classificada, mas, para seu propósito, use o LinkedHashSet .

Também a partir dos documentos,

"Esta implementação poupa seus clientes do pedido geralmente caótico não especificado fornecido pelo HashSet, sem incorrer no aumento do custo associado ao TreeSet. Ele pode ser usado para produzir uma cópia de um conjunto que tenha a mesma ordem que o original, independentemente do original. implementação do conjunto: "

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

Lakshman
fonte
9

Set é apenas uma interface. Para manter a ordem, é necessário usar uma implementação específica dessa interface e da subinterface SortedSet, por exemplo, TreeSet ou LinkedHashSet. Você pode agrupar seu conjunto desta maneira:

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

Aqui está um rápido resumo das características do pedido das Setimplementações padrão disponíveis em Java:

  1. mantenha a ordem de inserção: LinkedHashSet e CopyOnWriteArraySet (thread-safe)
  2. mantenha os itens classificados no conjunto: TreeSet , EnumSet (específico para enumerações) e ConcurrentSkipListSet (sem fio)
  3. não mantém os itens em nenhuma ordem específica: HashSet (o que você tentou)

Para o seu caso específico, você pode classificar os itens primeiro e depois usar qualquer um de 1 ou 2 (provavelmente LinkedHashSetou TreeSet). Ou, alternativamente e com mais eficiência , você pode adicionar dados não classificados a um TreeSetque cuidará da classificação automaticamente para você.

assylias
fonte
7

Para manter o pedido, use Listou a LinkedHashSet.

JHS
fonte
1
É LinkedHashSet, não ... Map.
Marko Topolnik
Eu preciso de um Set não uma lista, eu preciso de um conjunto que também mantém a ordem de injeção dos objetos acho
White_King
5

Um LinkedHashSet é uma versão ordenada do HashSet que mantém uma lista duplamente vinculada em todos os elementos. Use esta classe em vez do HashSet quando se importar com a ordem da iteração.

Danail Tsvetanov
fonte
3

Do javadoc para Set.iterator():

Retorna um iterador sobre os elementos neste conjunto. Os elementos são retornados em uma ordem específica (a menos que esse conjunto seja uma instância de alguma classe que forneça uma garantia).

E, como já afirmado por shuuchan , a TreeSeté uma implementação Setque possui uma ordem garantida:

Os elementos são ordenados usando sua ordem natural ou por um Comparador fornecido no momento da criação do conjunto, dependendo de qual construtor é usado.

hmjd
fonte
3

Normalmente, o set não mantém o pedido, como o HashSet, para encontrar rapidamente um emelent, mas você pode tentar o LinkedHashSet, pois ele manterá o pedido que você fez.

user1335794
fonte
1

Existem 2 coisas diferentes.

  1. Classifique os elementos em um conjunto. Para o qual temos SortedSet e implementações similares.
  2. Manter ordem de inserção em um conjunto. Para o qual LinkedHashSet e CopyOnWriteArraySet (sem fio) podem ser usados.
Aruna
fonte
0

A própria interface Set não estipula nenhuma ordem específica. O SortedSet faz no entanto.

Jens Borgland
fonte
-2

Somente SortedSetpode fazer o pedido doSet


fonte
A questão é sobre a retenção da ordem de inserção (que por acaso é classificada).
Assylias 25/05