Un HashMap o (Map en JAVA) es un mapeo de clave-valor, lo que significa que cada clave se asigna exactamente a un valor y que podemos usar la clave para recuperar el valor correspondiente de un HashMap. A diferencia de las colecciones, que guardan los valores de forma ordenada y cuyo indice es simpre un número entero (int), los HashMap guardan sus valores con un indice definido por el programador cómo por ejemplo un String.
Vídeo explicativo
Crear un HashMap
La forma más fácil de crear un HashMap es usando su constructor con los genéricos definidos:
HashMap<String, Empleado> empleadosPorNombre = new HashMap<>();
Aunque también podremos usar la interfaz Map para inicializar nuestro objecto:
Map<String, Empleado> empleadosPorNombre = new HashMap<>();
Métodos en HashMap
Put
El método put nos permite agregar valores dependiendo de un indice a nuestro HashMap:
Map<String, Empleado> empleadosPorNombre = new HashMap<>();
productsByName.put("Juan", new Empleado());
Get
El método get nos permite obtener valores dependiendo de un indice a nuestro HashMap:
Map<String, Empleado> empleadosPorNombre = new HashMap<>();
Empleado empleadoJuan = productsByName.get("Juan");
Remove
El método remove nos permite eliminar valores dependiendo de un indice a nuestro HashMap:
Map<String, Empleado> empleadosPorNombre = new HashMap<>();
productsByName.remove("Juan");
Clear
El método clear nos permite borrar todo nuestro HashMap:
Map<String, Empleado> empleadosPorNombre = new HashMap<>();
productsByName.clear();
KeySet
El método keySet nos permite obtener todos las claves de nuestro HashMap como array:
Map<String, Empleado> empleadosPorNombre = new HashMap<>();
productsByName.get("Juan");
Iterar un HashMap
Gracias al método KeySet podemos recorrer nuestro HashMap y obtener todos su valores:
for(String clave : empleadosPorNombre.keySet()) {
Empleado empleado = empleadosPorNombre.get(clave);
}
El indice
Podemos usar cualquier clase como clave en nuestro HashMap. Sin embargo, para que el mapa funcione correctamente, debemos proporcionar una implementación para equals() y hashCode(). Digamos que queremos tener un mapa con el empleado como clave y el salario como valor:
HashMap<Empleado, Integer> salarioPorEmpleado = new HashMap<>();
salarioPorEmpleado.put(empleadoJuan, 5000);
Deberemos de sobreescribir nuestro equals() y hashCode() en la clase Empleado para que nuestra HashMap reconozca a un objeto Empleado como un indice. Para más información puedes ver el artículo, aquí.
Inmutabilidad del indice
En la mayoría de los casos, deberíamos usar claves inmutables. O al menos, debemos ser conscientes de las consecuencias de utilizar claves mutables.
Veamos qué sucede cuando nuestra clave cambia después de que la usamos para almacenar un valor en un mapa.
Para este ejemplo, crearemos IndiceHash:
public class IndiceHash {
private Integer indice;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
IndiceHash that = (IndiceHash) o;
return Objects.equals(indice, that.indice);
}
@Override
public int hashCode() {
return Objects.hash(indice);
}
}
Y esta es la lógica:
IndiceHash clave = new IndiceHash(1);
Map<IndiceHash, String> elementos = new IndiceHash<>();
elementos.put(key, "success");
elementos.setIndice(2);
System.out.println(elementos.get(clave));
Como podemos ver, ya no podemos obtener el valor correspondiente una vez que la clave ha cambiado, en su lugar, se devuelve null. Esto se debe a que HashMap está buscando en con el indice equivocado.
El caso de prueba anterior puede ser sorprendente si no tenemos una buena comprensión de cómo funciona internamente HashMap.