Java ConcurrentHashMap

En este tutorial, aprenderemos sobre la clase Java ConcurrentHashMap y sus operaciones con la ayuda de ejemplos.

La ConcurrentHashMapclase 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.ConcurrentHashMappaquete. 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 ConcurrentHashMapclase 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 mapa
  • putAll() - inserta todas las entradas del mapa especificado en este mapa
  • putIfAbsent() - 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 mapa
  • keySet() - devuelve un conjunto de todas las claves del mapa
  • values() - 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. Devuelve nullsi 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 mapa
  • remove(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 entry
  • forEachKey() - executes the specified function for each key
  • forEachValue() - 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 mappings
  • searchKeys() - search function is only applied to the keys
  • searchValues() - 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 function
  • reduceKeys() - returns the result of gathering all the keys using the specified reducer function
  • reduceValues() - 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 like forEach(), search() and reduce().

Why ConcurrentHashMap?

  • La ConcurrentHashMapclase 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.

Articulos interesantes...