En este tutorial, aprenderemos sobre la clase Java ConcurrentHashMap y sus operaciones con la ayuda de ejemplos.
La ConcurrentHashMap
clase del marco de colecciones de Java proporciona un mapa seguro para subprocesos. Es decir, varios subprocesos pueden acceder al mapa a la vez sin afectar la coherencia de las entradas en un mapa.
Implementa la interfaz ConcurrentMap.
Crear un ConcurrentHashMap
Para crear un mapa hash concurrente, primero debemos importar el java.util.concurrent.ConcurrentHashMap
paquete. Una vez que importamos el paquete, así es como podemos crear hashmaps concurrentes en Java.
// ConcurrentHashMap with capacity 8 and load factor 0.6 ConcurrentHashMap numbers = new ConcurrentHashMap(8, 0.6f);
En el código anterior, hemos creado un hashmap concurrente llamado números.
Aquí,
- Clave: un identificador único que se utiliza para asociar cada elemento (valor) en un mapa.
- Valor: elementos asociados por claves en un mapa
Note la pieza new ConcurrentHashMap(8, 0.6)
. Aquí, el primer parámetro es la capacidad y el segundo parámetro es loadFactor .
- capacidad : la capacidad de este mapa es 8. Es decir, puede almacenar 8 entradas.
- loadFactor : el factor de carga de este mapa es 0.6. Esto significa que cada vez que nuestra tabla hash se llena en un 60%, las entradas se mueven a una nueva tabla hash del doble del tamaño de la tabla hash original.
Capacidad y factor de carga predeterminados
Es posible crear un mapa hash concurrente sin definir su capacidad y factor de carga. Por ejemplo,
// ConcurrentHashMap with default capacity and load factor ConcurrentHashMap numbers1 = new ConcurrentHashMap();
Por defecto,
- la capacidad del mapa será de 16
- el factor de carga será 0,75
Creación de ConcurrentHashMap desde otros mapas
Así es como podemos crear un mapa hash concurrente que contenga todos los elementos de otros mapas.
import java.util.concurrent.ConcurrentHashMap; import java.util.HashMap; class Main ( public static void main(String() args) ( // Creating a hashmap of even numbers HashMap evenNumbers = new HashMap(); evenNumbers.put("Two", 2); evenNumbers.put("Four", 4); System.out.println("HashMap: " + evenNumbers); // Creating a concurrent hashmap from other map ConcurrentHashMap numbers = new ConcurrentHashMap(evenNumbers); numbers.put("Three", 3); System.out.println("ConcurrentHashMap: " + numbers); ) )
Salida
HashMap: (Cuatro = 4, Dos = 2) ConcurrentHashMap: (Cuatro = 4, Dos = 2, Tres = 3)
Métodos de ConcurrentHashMap
La ConcurrentHashMap
clase proporciona métodos que nos permiten realizar varias operaciones en el mapa.
Insertar elementos en ConcurrentHashMap
put()
- inserta la asignación de clave / valor especificada en el mapaputAll()
- inserta todas las entradas del mapa especificado en este mapaputIfAbsent()
- inserta la asignación de clave / valor especificada en el mapa si la clave especificada no está presente en el mapa
Por ejemplo,
import java.util.concurrent.ConcurrentHashMap; class Main ( public static void main(String() args) ( // Creating ConcurrentHashMap of even numbers ConcurrentHashMap evenNumbers = new ConcurrentHashMap(); // Using put() evenNumbers.put("Two", 2); evenNumbers.put("Four", 4); // Using putIfAbsent() evenNumbers.putIfAbsent("Six", 6); System.out.println("ConcurrentHashMap of even numbers: " + evenNumbers); //Creating ConcurrentHashMap of numbers ConcurrentHashMap numbers = new ConcurrentHashMap(); numbers.put("One", 1); // Using putAll() numbers.putAll(evenNumbers); System.out.println("ConcurrentHashMap of numbers: " + numbers); ) )
Salida
ConcurrentHashMap de números pares: (Seis = 6, Cuatro = 4, Dos = 2) ConcurrentHashMap de números: (Seis = 6, Uno = 1, Cuatro = -4, Dos = 2)
Acceder a los elementos ConcurrentHashMap
1. Usando entrySet (), keySet () y values ()
entrySet()
- devuelve un conjunto de todo el mapeo clave / valor del mapakeySet()
- devuelve un conjunto de todas las claves del mapavalues()
- devuelve un conjunto de todos los valores del mapa
Por ejemplo,
import java.util.concurrent.ConcurrentHashMap; class Main ( public static void main(String() args) ( ConcurrentHashMap numbers = new ConcurrentHashMap(); numbers.put("One", 1); numbers.put("Two", 2); numbers.put("Three", 3); System.out.println("ConcurrentHashMap: " + numbers); // Using entrySet() System.out.println("Key/Value mappings: " + numbers.entrySet()); // Using keySet() System.out.println("Keys: " + numbers.keySet()); // Using values() System.out.println("Values: " + numbers.values()); ) )
Salida
ConcurrentHashMap: (Uno = 1, Dos = 2, Tres = 3) Asignaciones clave / valor: (Uno = 1, Dos = 2, Tres = 3) Claves: (Uno, Dos, Tres) Valores: (1, 2, 3 )
2. Usando get () y getOrDefault ()
get()
- Devuelve el valor asociado con la clave especificada. Devuelvenull
si no se encuentra la clave.getOrDefault()
- Devuelve el valor asociado con la clave especificada. Devuelve el valor predeterminado especificado si no se encuentra la clave.
Por ejemplo,
import java.util.concurrent.ConcurrentHashMap; class Main ( public static void main(String() args) ( ConcurrentHashMap numbers = new ConcurrentHashMap(); numbers.put("One", 1); numbers.put("Two", 2); numbers.put("Three", 3); System.out.println("ConcurrentHashMap: " + numbers); // Using get() int value1 = numbers.get("Three"); System.out.println("Using get(): " + value1); // Using getOrDefault() int value2 = numbers.getOrDefault("Five", 5); System.out.println("Using getOrDefault(): " + value2); ) )
Salida
ConcurrentHashMap: (Uno = 1, Dos = 2, Tres = 3) Usando get (): 3 Usando getOrDefault (): 5
Eliminar elementos de ConcurrentHashMap
remove(key)
- devuelve y elimina la entrada asociada con la clave especificada del maparemove(key, value)
- removes the entry from the map only if the specified key mapped to the specified value and return a boolean value
For example,
import java.util.concurrent.ConcurrentHashMap; class Main ( public static void main(String() args) ( ConcurrentHashMap numbers = new ConcurrentHashMap(); numbers.put("One", 1); numbers.put("Two", 2); numbers.put("Three", 3); System.out.println("ConcurrentHashMap: " + numbers); // remove method with single parameter int value = numbers.remove("Two"); System.out.println("Removed value: " + value); // remove method with two parameters boolean result = numbers.remove("Three", 3); System.out.println("Is the entry (Three=3) removed? " + result); System.out.println("Updated ConcurrentHashMap: " + numbers); ) )
Output
ConcurrentHashMap: (One=1, Two=2, Three=3) Removed value: 2 Is the entry (Three=3) removed? True Updated ConcurrentHashMap: (One=1)
Bulk ConcurrentHashMap Operations
The ConcurrentHashMap
class provides different bulk operations that can be applied safely to concurrent maps.
1. forEach() Method
The forEach()
method iterates over our entries and executes the specified function.
It includes two parameters.
- parallelismThreshold - It specifies that after how many elements operations in a map are executed in parallel.
- transformer - This will transform the data before the data is passed to the specified function.
For example,
import java.util.concurrent.ConcurrentHashMap; class Main ( public static void main(String() args) ( ConcurrentHashMap numbers = new ConcurrentHashMap(); numbers.put("One", 1); numbers.put("Two", 2); numbers.put("Three", 3); System.out.println("ConcurrentHashMap: " + numbers); // forEach() without transformer function numbers.forEach(4, (k, v) -> System.out.println("key: " + k + " value: " + v)); // forEach() with transformer function System.out.print("Values are "); numbers.forEach(4, (k, v) -> v, (v) -> System.out.print(v + ", ")); ) )
Output
ConcurrentHashMap: (One = 1, Two = 2, Three = 3) key: One value: 1 key: Two value: 2 key: Three value: 3 Values are 1, 2, 3,
In the above program, we have used parallel threshold 4. This means if the map contains 4 entries, the operation will be executed in parallel.
Variation of forEach() Method
forEachEntry()
- executes the specified function for each entryforEachKey()
- executes the specified function for each keyforEachValue()
- executes the specified function for each value
2. search() Method
The search()
method searches the map based on the specified function and returns the matched entry.
Here, the specified function determines what entry is to be searched.
It also includes an optional parameter parallelThreshold. The parallel threshold specifies that after how many elements in the map the operation is executed in parallel.
For example,
import java.util.concurrent.ConcurrentHashMap; class Main ( public static void main(String() args) ( ConcurrentHashMap numbers = new ConcurrentHashMap(); numbers.put("One", 1); numbers.put("Two", 2); numbers.put("Three", 3); System.out.println("ConcurrentHashMap: " + numbers); // Using search() String key = numbers.search(4, (k, v) -> (return v == 3 ? k: null;)); System.out.println("Searched value: " + key); ) )
Output
ConcurrentHashMap: (One=1, Two=2, Three=3) Searched value: Three
Variants of search() Method
searchEntries()
- search function is applied to key/value mappingssearchKeys()
- search function is only applied to the keyssearchValues()
- search function is only applied to the values
3. reduce() Method
The reduce()
method accumulates (gather together) each entry in a map. This can be used when we need all the entries to perform a common task, like adding all the values of a map.
It includes two parameters.
- parallelismThreshold - It specifies that after how many elements, operations in a map are executed in parallel.
- transformer - This will transform the data before the data is passed to the specified function.
For example,
import java.util.concurrent.ConcurrentHashMap; class Main ( public static void main(String() args) ( ConcurrentHashMap numbers = new ConcurrentHashMap(); numbers.put("One", 1); numbers.put("Two", 2); numbers.put("Three", 3); System.out.println("ConcurrentHashMap: " + numbers); // Using search() int sum = numbers.reduce(4, (k, v) -> v, (v1, v2) -> v1 + v2); System.out.println("Sum of all values: " + sum); ) )
Output
ConcurrentHashMap: (One=1, Two=2, Three=3) Sum of all values: 6
In the above program, notice the statement
numbers.reduce(4, (k, v) -> v, (v1, v2) -> v1+v2);
Here,
- 4 is a parallel threshold
- (k, v) -> v is a transformer function. It transfers the key/value mappings into values only.
- (v1, v2) -> v1+v2 is a reducer function. It gathers together all the values and adds all values.
Variants of reduce() Method
reduceEntries()
- returns the result of gathering all the entries using the specified reducer functionreduceKeys()
- returns the result of gathering all the keys using the specified reducer functionreduceValues()
- returns the result of gathering all the values using the specified reducer function
ConcurrentHashMap vs HashMap
Here are some of the differences between ConcurrentHashMap
and HashMap,
ConcurrentHashMap
is a thread-safe collection. That is, multiple threads can access and modify it at the same time.ConcurrentHashMap
provides methods for bulk operations likeforEach()
,search()
andreduce()
.
Why ConcurrentHashMap?
- La
ConcurrentHashMap
clase permite que varios subprocesos accedan a sus entradas al mismo tiempo. - De forma predeterminada, el mapa de hash concurrente se divide en 16 segmentos . Esta es la razón por la que se permite que 16 subprocesos modifiquen simultáneamente el mapa al mismo tiempo. Sin embargo, cualquier número de subprocesos puede acceder al mapa a la vez.
- El
putIfAbsent()
método no anulará la entrada en el mapa si la clave especificada ya existe. - Proporciona su propia sincronización.