Java ConcurrentHashMap
Java ConcurrentHashMap
Dans ce didacticiel, nous allons découvrir la classe Java ConcurrentHashMap et ses opérations à l'aide d'exemples.
Le ConcurrentHashMap
La classe du framework de collections Java fournit une carte thread-safe. Autrement dit, plusieurs threads peuvent accéder à la carte à la fois sans affecter la cohérence des entrées dans une carte.
Il implémente l'interface ConcurrentMap.
Créer un ConcurrentHashMap
Afin de créer un hashmap concurrent, nous devons importer le java.util.concurrent.ConcurrentHashMap
paquet d'abord. Une fois le package importé, voici comment créer des hashmaps simultanés en Java.
// ConcurrentHashMap with capacity 8 and load factor 0.6
ConcurrentHashMap<Key, Value> numbers = new ConcurrentHashMap<>(8, 0.6f);
Dans le code ci-dessus, nous avons créé un hashmap simultané nommé numbers .
Ici,
- Clé - un identifiant unique utilisé pour associer chaque élément (valeur) dans une carte
- Valeur - éléments associés par clés dans une carte
Remarquez la partie new ConcurrentHashMap<>(8, 0.6)
. Ici, le premier paramètre est la capacité et le deuxième paramètre est loadFactor .
- capacité - La capacité de cette carte est de 8. Cela signifie qu'elle peut stocker 8 entrées.
- facteur de charge - Le facteur de charge de cette carte est de 0,6. Cela signifie que chaque fois que notre table de hachage est remplie à 60 %, les entrées sont déplacées vers une nouvelle table de hachage d'une taille double de la table de hachage d'origine.
Capacité et facteur de charge par défaut
Il est possible de créer un hashmap simultané sans définir sa capacité et son facteur de charge. Par exemple,
// ConcurrentHashMap with default capacity and load factor
ConcurrentHashMap<Key, Value> numbers1 = new ConcurrentHashMap<>();
Par défaut,
- la capacité de la carte sera de 16
- le facteur de charge sera de 0,75
Créer ConcurrentHashMap à partir d'autres cartes
Voici comment nous pouvons créer un hashmap concurrent contenant tous les éléments des autres cartes.
import java.util.concurrent.ConcurrentHashMap;
import java.util.HashMap;
class Main {
public static void main(String[] args) {
// Creating a hashmap of even numbers
HashMap<String, Integer> evenNumbers = new HashMap<>();
evenNumbers.put("Two", 2);
evenNumbers.put("Four", 4);
System.out.println("HashMap: " + evenNumbers);
// Creating a concurrent hashmap from other map
ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(evenNumbers);
numbers.put("Three", 3);
System.out.println("ConcurrentHashMap: " + numbers);
}
}
Sortie
HashMap: {Four=4, Two=2} ConcurrentHashMap: {Four=4, Two=2, Three=3}
Méthodes de ConcurrentHashMap
Le ConcurrentHashMap
fournit des méthodes qui nous permettent d'effectuer diverses opérations sur la carte.
Insérer des éléments dans ConcurrentHashMap
put()
- insère le mappage clé/valeur spécifié dans la carteputAll()
- insère toutes les entrées de la carte spécifiée dans cette carteputIfAbsent()
- insère le mappage clé/valeur spécifié dans la carte si la clé spécifiée n'est pas présente dans la carte
Par exemple,
import java.util.concurrent.ConcurrentHashMap;
class Main {
public static void main(String[] args) {
// Creating ConcurrentHashMap of even numbers
ConcurrentHashMap<String, Integer> 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<String, Integer> numbers = new ConcurrentHashMap<>();
numbers.put("One", 1);
// Using putAll()
numbers.putAll(evenNumbers);
System.out.println("ConcurrentHashMap of numbers: " + numbers);
}
}
Sortie
ConcurrentHashMap of even numbers: {Six=6, Four=4, Two=2} ConcurrentHashMap of numbers: {Six=6, One=1, Four=-4, Two=2}
Accéder aux éléments ConcurrentHashMap
entrySet()
- renvoie un ensemble de tous les mappages clé/valeur de la cartekeySet()
- renvoie un ensemble de toutes les clés de la cartevalues()
- renvoie un ensemble de toutes les valeurs de la carte
Par exemple,
import java.util.concurrent.ConcurrentHashMap;
class Main {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> 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());
}
}
Sortie
ConcurrentHashMap: {One=1, Two=2, Three=3} Key/Value mappings: [One=1, Two=2, Three=3] Keys: [One, Two, Three] Values: [1, 2, 3]
get()
- Renvoie la valeur associée à la clé spécifiée. Renvoienull
si la clé n'est pas trouvée.getOrDefault()
- Renvoie la valeur associée à la clé spécifiée. Renvoie la valeur par défaut spécifiée si la clé est introuvable.
Par exemple,
import java.util.concurrent.ConcurrentHashMap;
class Main {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> 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);
}
}
Sortie
ConcurrentHashMap: {One=1, Two=2, Three=3} Using get(): 3 Using getOrDefault(): 5
Supprimer les éléments ConcurrentHashMap
remove(key)
- renvoie et supprime l'entrée associée à la clé spécifiée de la carteremove(key, value)
- supprime l'entrée de la carte uniquement si la clé spécifiée correspond à la valeur spécifiée et renvoie une valeur booléenne
Par exemple,
import java.util.concurrent.ConcurrentHashMap;
class Main {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> 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);
}
}
Sortie
ConcurrentHashMap: {One=1, Two=2, Three=3} Removed value: 2 Is the entry {Three=3} removed? True Updated ConcurrentHashMap: {One=1}
Opérations HashMap simultanées en masse
Le ConcurrentHashMap
fournit différentes opérations en bloc qui peuvent être appliquées en toute sécurité à des cartes simultanées.
1. Méthode forEach()
Le forEach()
la méthode itère sur nos entrées et exécute la fonction spécifiée.
Il comprend deux paramètres.
- seuil de parallélisme - Il précise qu'après combien d'opérations d'éléments dans une carte sont exécutées en parallèle.
- transformateur - Cela transformera les données avant que les données ne soient transmises à la fonction spécifiée.
Par exemple,
import java.util.concurrent.ConcurrentHashMap;
class Main {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> 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 + ", "));
}
}
Sortie
ConcurrentHashMap: {One = 1, Two = 2, Three = 3} key: One value: 1 key: Two value: 2 key: Three value: 3 Values are 1, 2, 3,
Dans le programme ci-dessus, nous avons utilisé le seuil parallèle 4 . Cela signifie que si la carte contient 4 entrées, l'opération sera exécutée en parallèle.
Variante de la méthode forEach()
forEachEntry()
- exécute la fonction spécifiée pour chaque entréeforEachKey()
- exécute la fonction spécifiée pour chaque toucheforEachValue()
- exécute la fonction spécifiée pour chaque valeur
2. Méthode search()
Le search()
La méthode recherche la carte en fonction de la fonction spécifiée et renvoie l'entrée correspondante.
Ici, la fonction spécifiée détermine quelle entrée doit être recherchée.
Il inclut également un paramètre facultatif parallelThreshold . Le seuil parallèle spécifie qu'après combien d'éléments dans la carte l'opération est exécutée en parallèle.
Par exemple,
import java.util.concurrent.ConcurrentHashMap;
class Main {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> 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);
}
}
Sortie
ConcurrentHashMap: {One=1, Two=2, Three=3} Searched value: Three
Variantes de la méthode search()
searchEntries()
- la fonction de recherche est appliquée aux mappages clé/valeursearchKeys()
- la fonction de recherche n'est appliquée qu'aux cléssearchValues()
- la fonction de recherche n'est appliquée qu'aux valeurs
3. méthode reduce()
Le reduce()
La méthode accumule (rassemble) chaque entrée dans une carte. Cela peut être utilisé lorsque nous avons besoin de toutes les entrées pour effectuer une tâche courante, comme ajouter toutes les valeurs d'une carte.
Il comprend deux paramètres.
- seuil de parallélisme - Il précise qu'après combien d'éléments, les opérations d'une carte sont exécutées en parallèle.
- transformateur - Cela transformera les données avant que les données ne soient transmises à la fonction spécifiée.
Par exemple,
import java.util.concurrent.ConcurrentHashMap;
class Main {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> 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);
}
}
Sortie
ConcurrentHashMap: {One=1, Two=2, Three=3} Sum of all values: 6
Dans le programme ci-dessus, notez la déclaration
numbers.reduce(4, (k, v) -> v, (v1, v2) -> v1+v2);
Ici,
- 4 est un seuil parallèle
- (k, v) -> v est une fonction de transformateur. Il transfère les mappages clé/valeur en valeurs uniquement.
- (v1, v2) -> v1+v2 est une fonction réductrice. Il rassemble toutes les valeurs et additionne toutes les valeurs.
Variantes de la méthode reduce()
reduceEntries()
- renvoie le résultat de la collecte de toutes les entrées à l'aide de la fonction de réduction spécifiéereduceKeys()
- renvoie le résultat de la collecte de toutes les clés à l'aide de la fonction de réduction spécifiéereduceValues()
- renvoie le résultat de la collecte de toutes les valeurs à l'aide de la fonction de réduction spécifiée
ConcurrentHashMap vs HashMap
Voici quelques-unes des différences entre ConcurrentHashMap
et HashMap,
ConcurrentHashMap
est un thread-safe le recueil. Autrement dit, plusieurs threads peuvent y accéder et le modifier en même temps.ConcurrentHashMap
fournit des méthodes pour les opérations en bloc commeforEach()
,search()
etreduce()
.
Pourquoi ConcurrentHashMap ?
- Le
ConcurrentHashMap
permet à plusieurs threads d'accéder simultanément à ses entrées. - Par défaut, le hashmap simultané est divisé en 16 segments . C'est la raison pour laquelle 16 threads sont autorisés à modifier simultanément la carte en même temps. Cependant, n'importe quel nombre de threads peut accéder à la carte à la fois.
- Le
putIfAbsent()
La méthode ne remplacera pas l'entrée dans la carte si la clé spécifiée existe déjà. - Il fournit sa propre synchronisation.
Java