¿Se garantiza el pedido para la devolución de claves y valores de un objeto LinkedHashMap?

162

Sé que LinkedHashMaptiene un orden de iteración predecible (orden de inserción). ¿El Setdevuelto por LinkedHashMap.keySet()y el Collectiondevuelto por LinkedHashMap.values()también mantienen este orden?

usuario256239
fuente
1
Puesto que todas las respuestas abordan el tema de la values(), así como keySet(), he ampliado la cuestión de incluir eso. Esto significa que se pueden cerrar más preguntas como duplicados de esto.
Duncan Jones

Respuestas:

226

La interfaz de Mapa proporciona tres vistas de colección , que permiten que los contenidos de un mapa se vean como un conjunto de claves, una colección de valores o un conjunto de asignaciones de clave-valor. El orden de un mapa se define como el orden en el que los iteradores en las vistas de colección del mapa devuelven sus elementos. Algunas implementaciones de mapas, como la TreeMap clase, ofrecen garantías específicas en cuanto a su orden; otros, como la HashMapclase, no lo hacen.

- Mapa

Esta lista vinculada define el orden de iteración, que normalmente es el orden en que se insertaron las claves en el mapa ( orden de inserción ).

- LinkedHashMap

Así que, sí, keySet(), values(), y entrySet()(las tres vistas de recogida mencionado) valores de retorno en el orden de los usos internos lista enlazada. Y sí, el JavaDoc lo garantiza Mapy lo LinkedHashMapgarantiza.

Ese es el punto de esta clase, después de todo.

Powerlord
fuente
8
la iteración sobre el mapa también se realiza más rápido usando un LinkedHashMap que un HashMap.
Thierry
2
values ​​() devuelve una colección. No es una lista. ¿Cómo lo mantiene en orden?
Dejell
77
@Dejel Collectiones solo la clase base de los valores que devuelve (). La implementación de la Colección que devuelve aún está controlada por LinkedHashMap. En LinkedHashMapel caso, está devolviendo una LinkedValuesinstancia, una clase privada dentro de LinkedHashMap.java.
Powerlord
2
El conjunto de claves de LinkedHashMap en mi caso NO está en el orden representado en el mapa. Muy perplejo por esto.
Amalgovinus
2
Gracias por vincular a la documentación (desde Map) que vincula explícitamente el orden de un mapa a los iteradores en las vistas de colección del mapa (y dejar en claro cuáles son esas vistas de colección). Esa fue la pieza que faltaba para mí.
LarsH
11

Mirando la fuente, parece que sí. keySet(), values()y entrySet()todos usan el mismo iterador de entrada internamente.

sblundy
fuente
1
Sería genial tener un enlace a los repositorios, pero soy vago :-) y, por supuesto, no es garantía de compatibilidad hacia adelante.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
6

¡No se confunda con LinkedHashMap.keySet()y LinkedHashMap.entrySet()devuelva Set y, por lo tanto, no debería garantizar el pedido!

Setes una interfaz con HashSet, TreeSetetc seres sus implementaciones. La HashSetimplementación de la Setinterfaz no garantiza el pedido. Pero lo TreeSethace. También lo LinkedHashSethace

Por lo tanto, depende de cómo Setse haya implementado LinkedHashMappara saber si la referencia Set establecida garantizará el pedido o no. Revisé el código fuente de LinkedHashMap, se ve así:

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

Por lo tanto, LinkedHashMap / HashMap tiene su propia implementación de Setie KeySet. Por lo tanto, no confunda esto con HashSet.

Además, el orden se mantiene por cómo se insertan los elementos en el cubo. Mire el addEntry(..)método LinkedHashMapy compárelo con el HashMapque resalta la diferencia principal entre HashMapy LinkedHashMap.

anzaan
fuente
44
Si bien esta respuesta definitivamente presenta información útil, en realidad no responde la pregunta. Básicamente está diciendo que PUEDEN tener un orden de iteración predecible.
Tuupertunut
5

Puedes suponer que sí. El Javadoc dice 'orden de iteración predecible', y los únicos iteradores disponibles en un Mapa son aquellos para keySet (), entrySet () y values ​​().

Por lo tanto, en ausencia de cualquier calificación adicional, está claramente destinado a aplicarse a todos esos iteradores.

Marqués de Lorne
fuente
0

AFAIK no está documentado, por lo que no puede asumirlo "formalmente". Sin embargo, es poco probable que la implementación actual cambie.

Si desea garantizar el orden, es posible que desee iterar sobre las entradas del mapa e insertarlas en un conjunto ordenado con una función de orden de su elección, aunque naturalmente pagará un costo de rendimiento.

Uri
fuente
¿Quieres decir que entrySet () garantiza el pedido, por keySet () no?
user256239
1
@kknight: no estoy seguro. el javadoc dice: "Esta lista vinculada define el orden de iteración, que normalmente es el orden en que se insertaron las claves en el mapa (orden de inserción)". Sin embargo, los JavaDocs para el JDK son muy ambiguos en general.
Uri
55
Si incluso entrySet () no garantiza el orden de iteración, ¿cuál es la diferencia entre LinkedHashMap y HashMap? ¿Cómo podemos aprovechar el orden de iteración predecible en una instancia de LinkedHashMap?
user256239
1
Ciertamente está documentado. La respuesta es completamente incorrecta.
Marqués de Lorne
-3

Mirando la interfaz, devuelve un simple Sety no un SortedSet. Entonces no hay garantías.

Antes de asumir una garantía implícita al observar la implementación (siempre es una mala idea), observe también las implementaciones en todas las demás implementaciones de Java :)

Podría crear mejor, por ejemplo, un TreeSet con keySet en el constructor.

extraneon
fuente
3
Mirando más de cerca la documentación, de hecho hay garantías. Como alguien ya escribió, ese es el punto de esta clase.
glglgl
-4

No creo que pueda presumir el orden de keySet () y values ​​().

Puedo escribir fácilmente una implementación de LinkedHashMap que te devuelva keySet () y valores () desordenados, siempre que cumpla con el contrato de estos dos métodos que se definen en Map y se anulan en HashMap.

Zoro
fuente
66
Todo el propósito de la LinkedHashMapclase es mantener el orden de los elementos mientras se itera el mapa y este comportamiento está bien especificado. Si escribe una subclase sin cumplir con la especificación de la clase base, entonces está haciendo algo muy mal.
zakinster