¿El orden de los valores recuperados de un HashMap es el orden de inserción?
Estoy intentando averiguar el orden en el que se pueden recuperar los valores de un HashMap. Aquí está el fragmento de código para el mismo.
import java.util.HashMap;
public class HashMapExample {
public static void main(String[] args) {
HashMap<Integer, String> hashmap = new HashMap<Integer, String>();
hashmap.put(1, "apple" );
hashmap.put(2, "lemon" );
hashmap.put(3, "orange" );
hashmap.put(4, "banana" );
hashmap.put(5, "litchi" );
hashmap.put(6, "mango" );
hashmap.put(7, "papaya" );
System.out.println(hashmap.size());
for (String key : hashmap.values()) {
System.out.println(key);
}
}
}
producción:
7
apple
lemon
orange
banana
litchi
mango
papaya
Los valores se imprimen en el orden en que se han insertado. ¿Es esto cierto en general? Esperaba que los valores se imprimieran en un orden arbitrario. Esto está usando Java 6.
Del Javadoc: HashMap
"la clase no garantiza el orden del mapa; en particular, no garantiza que el orden permanecerá constante en el tiempo".
Si necesita pedidos consistentes, puede usar LinkedHashMap
(para orden de inserción/acceso) o TreeMap
(para orden de comparación). Tenga en cuenta que estos mantienen el orden de las claves, no los valores.
Los valores se imprimen en el orden en que se han insertado. ¿Es esto cierto en general? Esperaba que los valores se imprimieran en orden aleatorio.
La HashMap
API no define el orden de iteración.
Sin embargo, si observa la implementación de HashMap, puede deducir que existe una relación transitoria compleja entre el orden de iteración, los valores hash de las claves, el orden en que se insertaron las claves y el tamaño de la tabla hash. Esta relación se codifica si la tabla hash cambia de tamaño 1 .
En su caso, está utilizando Integer
claves, lo que significa que los valores hash de las claves son los valores clave en sí. Además, insertó las entradas en orden clave. Esto lleva (¡fortuitamente!) a que el orden de iteración coincida con el orden de inserción. Pero si sigue insertando más claves, encontrará que el orden de iteración "se ajusta". Luego, a medida que la tabla pasa por una serie de cambios de tamaño, el orden se volverá cada vez más revuelto.
En resumen, lo que está viendo es un artefacto de la implementación de la tabla hash y del hashCode
método específico. No es algo que puedas (o debas) utilizar con sensatez. ¡Sobre todo porque puede cambiar ( y ha cambiado ) de una versión de Java a la siguiente!
1 - O en Java 8 o posterior, si la congestión de un depósito de hash/cadena de hash en particular hace que cambie de una lista simple a un árbol rojo-negro. Detalle de implementación profundo. Si tienes curiosidad, lee el código fuente.
Un LinkedHashMap es lo que buscas. Desde el documento, se diferencia de HashMap en que mantiene una lista doblemente enlazada que recorre todas sus entradas.
Pruebe LinkedHashMap si el orden es importante... consulte JavaDoc
la clase pública LinkedHashMap extiende HashMap
Implementación de tabla hash y lista vinculada de la interfaz Map, con orden de iteración predecible. Esta implementación se diferencia de HashMap en que mantiene una lista doblemente enlazada que recorre todas sus entradas. 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). Tenga en cuenta que el orden de inserción no se ve afectado si se vuelve a insertar una clave en el mapa. (Se reinserta una clave k en un mapa m si se invoca m.put(k, v) cuando m.containsKey(k) devolvería verdadero inmediatamente antes de la invocación).
Una colección relacionada es ConcurrentSkipListMap de java.util.concurrent . Una lista de omisión le permite recorrer las entradas en orden clave y también buscarlas en orden aleatorio (pero no tan rápido como un HashMap).
Hay un bonito subprograma de demostración de skiplist .