Menu

Java HashMap: put, get, iterar y patrones comunes

Cómo usar el HashMap de Java para búsquedas clave-valor: put, get, getOrDefault, containsKey, iterar sobre entradas y los patrones que más utilizarás.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Un Map almacena pares clave-valor

Un HashMap (de java.util) almacena asociaciones: cada clave se asigna a un valor, y buscas los valores por su clave en tiempo aproximadamente constante. Piensa en un diccionario: la palabra es la clave y la definición es el valor.

Los dos parámetros de tipo son <KeyType, ValueType>. Aquí las claves son String y los valores son Integer. Al igual que con ArrayList, normalmente declaras la variable con el tipo de la interfaz Map y construyes un HashMap.

put, get y sobrescritura

Dos cosas que conviene interiorizar:

  • Una clave es única. put con una clave existente reemplaza su valor y devuelve el anterior.
  • get sobre una clave inexistente devuelve null, no un error. Hacer el auto-unboxing de ese null a un int lanza una NullPointerException, una fuente habitual de errores.

getOrDefault evita la trampa del null

En lugar de comprobar null cada vez, pide un valor por defecto:

Esta es la forma más limpia de manejar búsquedas de elementos "tal vez presentes", y conduce directamente al patrón de HashMap más famoso.

Contar ocurrencias

Contar cuántas veces aparece cada elemento es la tarea de manual para un HashMap:

El patrón map.put(key, map.getOrDefault(key, 0) + 1) se lee como "toma el conteo actual (o cero), súmale uno y vuélvelo a guardar". Un equivalente más elegante es counts.merge(word, 1, Integer::sum).

Comprobar y eliminar

putIfAbsent(key, value) solo escribe cuando la clave no existe, útil para la inicialización perezosa.

Recorrer un HashMap

El bucle más común recorre entrySet(), dándote cada clave y valor juntos:

Si solo necesitas las claves o solo los valores:

También puedes usar forEach con una lambda: ages.forEach((name, age) -> System.out.println(name + ": " + age));.

El HashMap no conserva el orden

Un HashMap no garantiza ningún orden de iteración: es el que produce el hashing, y puede cambiar entre ejecuciones. Si necesitas un orden predecible:

  • LinkedHashMap conserva el orden de inserción.
  • TreeMap mantiene las claves ordenadas por su orden natural (o por un Comparator que proporciones).

Las tres implementan la interfaz Map, así que cambiar de una a otra es modificar una sola línea en el constructor.

Las claves deben ser hashables

HashMap encuentra las entradas haciendo hash de la clave, por lo que el hashCode() y el equals() de una clave deben ser coherentes entre sí. Los tipos integrados como String e Integer ya lo hacen correctamente. Si usas tu propia clase como clave, sobrescribe tanto equals como hashCode; de lo contrario, dos objetos que sean "iguales" en significado terminarán en cubetas distintas y tus búsquedas fallarán de forma misteriosa.

Siguiente: HashSet

Un HashMap responde a "¿qué valor está almacenado bajo esta clave?". Cuando solo te importa si algo está presente o no (un conjunto de valores únicos, sin datos asociados), la herramienta es HashSet, que viene a continuación.

Preguntas frecuentes

¿Cómo se crea un HashMap en Java?

Declaralo con dos parámetros de tipo (el tipo de la clave y el tipo del valor) y llama al constructor: Map<String, Integer> ages = new HashMap<>();. Luego añade entradas con ages.put("Ada", 36); y léelas con ages.get("Ada");. Importa java.util.HashMap y java.util.Map.

¿Cómo se recorre un HashMap en Java?

Itera sobre map.entrySet() con un bucle for-each para obtener cada clave y valor a la vez: for (Map.Entry<String, Integer> e : map.entrySet()) { ... }, leyendo e.getKey() y e.getValue(). También puedes recorrer map.keySet() para obtener solo las claves o map.values() para obtener solo los valores. Ten en cuenta que un HashMap no conserva el orden de inserción.

¿Cuál es la diferencia entre get y getOrDefault?

get(key) devuelve el valor de una clave, o null si la clave no existe, lo que puede provocar una NullPointerException si usas el resultado directamente. getOrDefault(key, fallback) devuelve el valor si está presente y, en caso contrario, el valor por defecto que pases, así evitas la comprobación de null. Es especialmente útil para contar: counts.put(c, counts.getOrDefault(c, 0) + 1).

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR