A ordem é garantida para o retorno de chaves e valores de um objeto LinkedHashMap?

162

Eu sei que LinkedHashMaptem uma ordem de iteração previsível (ordem de inserção). O Setdevolvido LinkedHashMap.keySet()e o Collectiondevolvido LinkedHashMap.values()também mantêm esse pedido?

user256239
fonte
1
Como todas as respostas abordam a questão values(), além disso keySet(), ampliei a questão para incluir isso. Isso significa que mais perguntas podem ser encerradas como duplicatas.
Duncan Jones

Respostas:

226

A interface Mapa fornece três visualizações de coleção , que permitem que o conteúdo de um mapa seja exibido como um conjunto de chaves, coleção de valores ou conjunto de mapeamentos de valores-chave. A ordem de um mapa é definida como a ordem na qual os iteradores nas visualizações de coleção do mapa retornam seus elementos. Algumas implementações de mapas, como a TreeMap classe, oferecem garantias específicas quanto à sua ordem; outros, como a HashMapturma, não.

- Mapa

Essa lista vinculada define a ordem da iteração, que normalmente é a ordem na qual as chaves foram inseridas no mapa ( ordem de inserção ).

- LinkedHashMap

Então, sim, keySet(), values(), e entrySet()(os três pontos de vista de recolha referido) valores de retorno na ordem dos usos da lista ligadas internos. E sim, o JavaDoc Mape o LinkedHashMapgarante.

Esse é o objetivo desta aula, afinal.

Powerlord
fonte
8
a iteração no mapa também é feita mais rapidamente usando um LinkedHashMap do que um HashMap.
Thierry
2
values ​​() retorna uma coleção. não é uma lista. como ele mantém isso em ordem?
Dejell
7
@Dejel Collectioné apenas a classe base para quais valores () retornam. A implementação da coleção retornada ainda é controlada pelo LinkedHashMap. No LinkedHashMapcaso, está retornando uma LinkedValuesinstância, uma classe privada dentro do LinkedHashMap.java.
Powerlord
2
O conjunto de chaves de um LinkedHashMap no meu caso NÃO está na ordem representada no mapa. Muito intrigado com isso.
Amalgovinus
2
Obrigado por vincular à documentação (de Map) que vincula explicitamente a ordem de um mapa aos iteradores nas visualizações de coleção do mapa (e esclarece quais são essas visualizações de coleção). Essa foi a peça que faltava para mim.
Larsh
11

Olhando para a fonte, parece que sim. keySet(), values()E entrySet()todos usam a mesma entrada iterador internamente.

esplêndido
fonte
1
Seria legal ter um link para os repositórios, mas eu sou preguiçoso :-) e, claro, não é garantia de compatibilidade direta.
Ciro Santilli escreveu:
6

Não se confunda com LinkedHashMap.keySet()e LinkedHashMap.entrySet()retorna conjunto e, portanto, não deve garantir ordenação!

Seté uma interface com HashSet, TreeSetetc, suas implementações. A HashSetimplementação da Setinterface não garante pedidos. Mas TreeSetfaz. Também LinkedHashSetfaz.

Portanto, depende de como Setfoi implementado LinkedHashMappara saber se a referência de retorno do conjunto garantirá o pedido ou não. Eu passei pelo código fonte do LinkedHashMap, fica assim:

private final class KeySet extends AbstractSet<K> {...}
public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> {...}

Assim, o LinkedHashMap / HashMap tem sua própria implementação de Setie KeySet. Portanto, não confunda isso com HashSet.

Além disso, a ordem é mantida pela forma como os elementos são inseridos no balde. Observe o addEntry(..)método de LinkedHashMape compare-o com o HashMapque destaca a principal diferença entre HashMape LinkedHashMap.

anzaan
fonte
4
Embora esta resposta definitivamente apresente informações úteis, na verdade não responde à pergunta. Basicamente, eles podem ter ordem de iteração previsível.
Tuupertunut
5

Você pode assumir isso. O Javadoc diz 'ordem de iteração previsível' e os únicos iteradores disponíveis em um mapa são aqueles para keySet (), entrySet () e valores ().

Portanto, na ausência de qualquer qualificação adicional, claramente se aplica a todos esses iteradores.

Marquês de Lorne
fonte
0

Como o AFAIK não está documentado, você não pode assumi-lo "formalmente". É improvável, no entanto, que a implementação atual mude.

Se você deseja garantir a ordem, pode iterar sobre o mapa que entra e inseri-los em um conjunto classificado com uma função de ordem de sua escolha, embora você esteja pagando um custo de desempenho, naturalmente.

Uri
fonte
Você quer dizer que entrySet () garante a ordem, por keySet () não?
User256239
1
@ kknight: Não tenho certeza. o javadoc declara: "Esta lista vinculada define a ordem da iteração, que normalmente é a ordem na qual as chaves foram inseridas no mapa (ordem de inserção).". No entanto, os JavaDocs para o JDK são muito ambíguos em geral.
Uri
5
Se mesmo entrySet () não garante a ordem da iteração, qual é a diferença entre o LinkedHashMap e o HashMap? Como podemos tirar proveito da ordem de iteração previsível em uma instância do LinkedHashMap?
User256239
1
Certamente está documentado. A resposta está completamente incorreta.
Marquês de Lorne
-3

Olhando para a interface, ele retorna um simples Sete não um SortedSet. Portanto, não há garantias.

Antes de assumir uma garantia implícita, observando a implementação (sempre uma má ideia), observe também as implementações em todas as outras implementações Java :)

É melhor criar, por exemplo, um TreeSet com o keySet no construtor.

extraneon
fonte
3
Olhando mais de perto a documentação, há realmente garantias. Como alguém já escreveu, esse é o ponto principal desta aula.
glglgl
-4

Eu não acho que você possa presumir a ordem de keySet () e values ​​().

Posso escrever facilmente uma implementação do LinkedHashMap que retorna keySet () e values ​​() desordenados, desde que cumpra o contrato desses dois métodos definidos no Map e substituídos no HashMap.

Zoro
fonte
6
O objetivo da LinkedHashMapclasse é manter a ordem dos elementos enquanto itera o mapa e esse comportamento é bem especificado. Se você escrever uma subclasse sem cumprir a especificação da classe base, estará fazendo algo muito errado.
Zakinster