Dominando Java ConcurrentHashMap: Operaciones, Ejemplos y Mejores Prácticas
Java ConcurrentHashMap
Explora la clase ConcurrentHashMap de Java, aprende a crearla y manipularla, y descubre sus ventajas clave con ejemplos de código prácticos.
La clase ConcurrentHashMap del framework de colecciones de Java ofrece una implementación de mapa thread-safe. Múltiples hilos pueden leer y escribir concurrentemente sin corromper la integridad del mapa.
Implementa la interfaz ConcurrentMap y es parte de java.util.concurrent.
Crear un ConcurrentHashMap
Primero, importa la clase:
import java.util.concurrent.ConcurrentHashMap;
Luego instánciala. Puedes especificar capacidad inicial y factor de carga, o confiar en los valores por defecto.
// Capacidad 8, factor de carga 0.6
ConcurrentHashMap<Clave, Valor> numeros = new ConcurrentHashMap<>(8, 0.6f);
Parámetros
capacidad– número inicial de buckets (8 en el ejemplo).factorDeCarga– dispara redimensionado cuando el mapa alcanza el 60% de llenado.
Constructor por defecto crea un mapa con capacidad 16 y factor de carga 0.75:
ConcurrentHashMap<Clave, Valor> numeros1 = new ConcurrentHashMap<>();
Creando ConcurrentHashMap desde Mapas Existentes
Puedes poblar un nuevo ConcurrentHashMap con las entradas de cualquier otro mapa.
import java.util.concurrent.ConcurrentHashMap;
import java.util.HashMap;
class Main {
public static void main(String[] args) {
HashMap<String, Integer> numerosPares = new HashMap<>();
numerosPares.put("Dos", 2);
numerosPares.put("Cuatro", 4);
System.out.println("HashMap: " + numerosPares);
ConcurrentHashMap<String, Integer> numeros = new ConcurrentHashMap<>(numerosPares);
numeros.put("Tres", 3);
System.out.println("ConcurrentHashMap: " + numeros);
}
}
Salida
HashMap: {Cuatro=4, Dos=2} ConcurrentHashMap: {Cuatro=4, Dos=2, Tres=3}
Métodos Clave de ConcurrentHashMap
Insertando Elementos
put(K key, V value)– Añade o reemplaza un mapeo.putAll(Map<? extends K, ? extends V> m)– Inserción en lote.putIfAbsent(K key, V value)– Inserta solo si la clave está ausente.
ConcurrentHashMap<String, Integer> numerosPares = new ConcurrentHashMap<>();
numerosPares.put("Dos", 2);
numerosPares.put("Cuatro", 4);
numerosPares.putIfAbsent("Seis", 6);
System.out.println("Números pares: " + numerosPares);
ConcurrentHashMap<String, Integer> numeros = new ConcurrentHashMap<>();
numeros.put("Uno", 1);
numeros.putAll(numerosPares);
System.out.println("Números: " + numeros);
Salida
Números pares: {Seis=6, Cuatro=4, Dos=2} Números: {Seis=6, Uno=1, Cuatro=4, Dos=2}
Accediendo a Elementos
Usa vistas de colección o métodos de recuperación clave/valor.
entrySet(),keySet(),values()– Devuelven colecciones de entradas, claves o valores.get(K key)– Recupera un valor onullsi está ausente.getOrDefault(K key, V defaultValue)– Recupera un valor o un default proporcionado.
ConcurrentHashMap<String, Integer> numeros = new ConcurrentHashMap<>();
numeros.put("Uno", 1);
numeros.put("Dos", 2);
numeros.put("Tres", 3);
System.out.println("Mapa: " + numeros);
System.out.println("Entradas: " + numeros.entrySet());
System.out.println("Claves: " + numeros.keySet());
System.out.println("Valores: " + numeros.values());
int val = numeros.get("Tres");
System.out.println("get(\"Tres\"): " + val);
int def = numeros.getOrDefault("Cinco", 5);
System.out.println("getOrDefault(\"Cinco\", 5): " + def);
Salida
Mapa: {Uno=1, Dos=2, Tres=3} Entradas: [Uno=1, Dos=2, Tres=3] Claves: [Uno, Dos, Tres] Valores: [1, 2, 3] get("Tres"): 3 getOrDefault("Cinco", 5): 5
Eliminando Entradas
remove(K key)– Elimina el mapeo y devuelve su valor.remove(K key, V value)– Elimina solo si el valor actual coincide; devuelve booleano.
ConcurrentHashMap<String, Integer> numeros = new ConcurrentHashMap<>();
numeros.put("Uno", 1);
numeros.put("Dos", 2);
numeros.put("Tres", 3);
int eliminado = numeros.remove("Dos");
System.out.println("Valor eliminado: " + eliminado);
boolean borrado = numeros.remove("Tres", 3);
System.out.println("¿Entrada {Tres=3} eliminada? " + borrado);
System.out.println("Mapa actualizado: " + numeros);
Salida
Valor eliminado: 2 ¿Entrada {Tres=3} eliminada? true Mapa actualizado: {Uno=1}
Operaciones en Lote (Bulk Operations)
Estos métodos aprovechan el paralelismo para procesar mapas grandes eficientemente.
forEach()
Itera sobre entradas, opcionalmente en paralelo, y aplica un consumidor.
numeros.forEach(4, (k, v) -> System.out.println("clave: " + k + " valor: " + v));
// Con transformador:
numeros.forEach(4, (k, v) -> v, (v) -> System.out.print(v + ", "));
Aquí 4 es el umbral de paralelismo – cuando el mapa tiene al menos 4 elementos, la operación puede ejecutarse concurrentemente.
search()
Encuentra una entrada que satisfaga un predicado. Devuelve la primera coincidencia.
String clave = numeros.search(4, (k, v) -> v == 3 ? k : null);
System.out.println("Clave buscada: " + clave);
reduce()
Agrega valores usando un reductor. Útil para sumas, productos o acumulaciones personalizadas.
int suma = numeros.reduce(4, (k, v) -> v, (v1, v2) -> v1 + v2);
System.out.println("Suma de valores: " + suma);
ConcurrentHashMap vs. HashMap
- Seguridad en hilos –
ConcurrentHashMappermite modificaciones concurrentes seguras;HashMapno es thread-safe. - Métodos en lote –
ConcurrentHashMapofreceforEach,searchyreducepara procesamiento paralelo.
Por Qué Usar ConcurrentHashMap
- Soporta alta concurrencia con bloqueo mínimo.
- Internamente dividido en 16 segmentos, permitiendo hasta 16 hilos modificando segmentos diferentes simultáneamente.
- Operaciones como
putIfAbsentprevienen sobrescrituras accidentales. - Sincronización integrada elimina la necesidad de bloqueos externos.
Java
- Dominar Operadores en Java: Tipos, Sintaxis y Ejemplos Prácticos
- Comentarios en Java: Tipos, Uso y Mejores Prácticas
- Dominar el Bucle for Mejorado en Java: Sintaxis, Ejemplos y Mejores Prácticas
- Dominar Strings en Java: Creación, Métodos y Mejores Prácticas
- Dominando interfaces en Java: Conceptos, implementación y mejores prácticas
- Dominando las clases internas anónimas en Java: Definición, sintaxis y ejemplos prácticos
- Dominando Try‑with‑Resources en Java: Gestión automática de recursos explicada
- Anotaciones en Java explicadas: Tipos, ubicación y ejemplos prácticos
- Aserciones en Java: Guía práctica para detectar bugs y asegurar fiabilidad del código
- Dominando los Algoritmos de Colecciones de Java: Ordenación, Mezcla y Más
- Generar números aleatorios en Java: Guía práctica con Random y Math.random