Java ConcurrentHashMap
Java ConcurrentHashMap
In deze zelfstudie leren we over de Java ConcurrentHashMap-klasse en zijn bewerkingen met behulp van voorbeelden.
De ConcurrentHashMap
klasse van het Java-verzamelingsraamwerk biedt een thread-veilige kaart. Dat wil zeggen dat meerdere threads tegelijk toegang hebben tot de kaart zonder de consistentie van de items in een kaart te beïnvloeden.
Het implementeert de ConcurrentMap-interface.
Maak een ConcurrentHashMap
Om een gelijktijdige hashmap te maken, moeten we de java.util.concurrent.ConcurrentHashMap
. importeren pakket eerst. Nadat we het pakket hebben geïmporteerd, kunnen we als volgt gelijktijdige hashmaps maken in Java.
// ConcurrentHashMap with capacity 8 and load factor 0.6
ConcurrentHashMap<Key, Value> numbers = new ConcurrentHashMap<>(8, 0.6f);
In de bovenstaande code hebben we een gelijktijdige hashmap gemaakt met de naam nummers .
Hier,
- Sleutel - een unieke identificatie die wordt gebruikt om elk element (waarde) in een kaart te associëren
- Waarde - elementen geassocieerd met sleutels in een kaart
Let op het onderdeel new ConcurrentHashMap<>(8, 0.6)
. Hier is de eerste parameter capaciteit en de tweede parameter is loadFactor .
- capaciteit - De capaciteit van deze kaart is 8. Dit betekent dat er 8 items kunnen worden opgeslagen.
- loadFactor - De belastingsfactor van deze kaart is 0,6. Dit betekent dat telkens wanneer onze hashtabel voor 60% is gevuld, de items worden verplaatst naar een nieuwe hashtabel die twee keer zo groot is als de oorspronkelijke hashtabel.
Standaardcapaciteit en belastingsfactor
Het is mogelijk om een gelijktijdige hashmap te maken zonder de capaciteit en belastingsfactor te definiëren. Bijvoorbeeld,
// ConcurrentHashMap with default capacity and load factor
ConcurrentHashMap<Key, Value> numbers1 = new ConcurrentHashMap<>();
Standaard,
- de capaciteit van de kaart is 16
- de belastingsfactor zal 0,75 zijn
ConcurrentHashMap maken van andere kaarten
Hier is hoe we een gelijktijdige hashmap kunnen maken die alle elementen van andere kaarten bevat.
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);
}
}
Uitvoer
HashMap: {Four=4, Two=2} ConcurrentHashMap: {Four=4, Two=2, Three=3}
Methoden van ConcurrentHashMap
De ConcurrentHashMap
class biedt methoden waarmee we verschillende bewerkingen op de kaart kunnen uitvoeren.
Elementen invoegen in ConcurrentHashMap
put()
- voegt de opgegeven sleutel/waarde-toewijzing in op de kaartputAll()
- voegt alle vermeldingen van de opgegeven kaart in op deze kaartputIfAbsent()
- voegt de gespecificeerde sleutel/waarde-toewijzing toe aan de kaart als de gespecificeerde sleutel niet aanwezig is in de kaart
Bijvoorbeeld,
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);
}
}
Uitvoer
ConcurrentHashMap of even numbers: {Six=6, Four=4, Two=2} ConcurrentHashMap of numbers: {Six=6, One=1, Four=-4, Two=2}
Toegang tot ConcurrentHashMap-elementen
entrySet()
- retourneert een set van alle sleutel/waarde-toewijzingen van de kaartkeySet()
- geeft een set van alle sleutels van de kaart terugvalues()
- geeft een set van alle waarden van de kaart terug
Bijvoorbeeld,
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());
}
}
Uitvoer
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()
- Retourneert de waarde die is gekoppeld aan de opgegeven sleutel. Retourneertnull
als de sleutel niet wordt gevonden.getOrDefault()
- Retourneert de waarde die is gekoppeld aan de opgegeven sleutel. Retourneert de opgegeven standaardwaarde als de sleutel niet wordt gevonden.
Bijvoorbeeld,
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);
}
}
Uitvoer
ConcurrentHashMap: {One=1, Two=2, Three=3} Using get(): 3 Using getOrDefault(): 5
ConcurrentHashMap-elementen verwijderen
remove(key)
- retourneert en verwijdert de invoer die is gekoppeld aan de opgegeven sleutel van de kaartremove(key, value)
- verwijdert het item alleen van de kaart als de opgegeven sleutel is toegewezen aan de opgegeven waarde en retourneert een booleaanse waarde
Bijvoorbeeld,
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);
}
}
Uitvoer
ConcurrentHashMap: {One=1, Two=2, Three=3} Removed value: 2 Is the entry {Three=3} removed? True Updated ConcurrentHashMap: {One=1}
Bulk ConcurrentHashMap-bewerkingen
De ConcurrentHashMap
class biedt verschillende bulkbewerkingen die veilig kunnen worden toegepast op gelijktijdige kaarten.
1. forEach() Methode
De forEach()
methode herhaalt onze invoer en voert de gespecificeerde functie uit.
Het bevat twee parameters.
- parallelismedrempel - Het specificeert dat na hoeveel elementen bewerkingen in een kaart parallel worden uitgevoerd.
- transformator - Hierdoor worden de gegevens getransformeerd voordat de gegevens worden doorgegeven aan de opgegeven functie.
Bijvoorbeeld,
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 + ", "));
}
}
Uitvoer
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 het bovenstaande programma hebben we parallelle drempel 4 . gebruikt . Dit betekent dat als de kaart 4 items bevat, de bewerking parallel zal worden uitgevoerd.
Variatie van forEach()-methode
forEachEntry()
- voert de opgegeven functie uit voor elke invoerforEachKey()
- voert de gespecificeerde functie uit voor elke toetsforEachValue()
- voert de opgegeven functie uit voor elke waarde
2. search() Methode
De search()
methode zoekt de kaart op basis van de opgegeven functie en retourneert de overeenkomende invoer.
Hier bepaalt de gespecificeerde functie naar welk item moet worden gezocht.
Het bevat ook een optionele parameter parallelThreshold . De parallelle drempel specificeert dat na hoeveel elementen op de kaart de bewerking parallel wordt uitgevoerd.
Bijvoorbeeld,
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);
}
}
Uitvoer
ConcurrentHashMap: {One=1, Two=2, Three=3} Searched value: Three
Varianten van de methode search()
searchEntries()
- zoekfunctie wordt toegepast op sleutel/waarde-toewijzingensearchKeys()
- zoekfunctie wordt alleen toegepast op de toetsensearchValues()
- zoekfunctie wordt alleen toegepast op de waarden
3. reduce() methode
De reduce()
methode accumuleert (verzamelt) elk item in een kaart. Dit kan worden gebruikt wanneer we alle items nodig hebben om een algemene taak uit te voeren, zoals het toevoegen van alle waarden van een kaart.
Het bevat twee parameters.
- parallelismedrempel - Het specificeert dat na hoeveel elementen, operaties in een kaart parallel worden uitgevoerd.
- transformator - Hierdoor worden de gegevens getransformeerd voordat de gegevens worden doorgegeven aan de opgegeven functie.
Bijvoorbeeld,
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);
}
}
Uitvoer
ConcurrentHashMap: {One=1, Two=2, Three=3} Sum of all values: 6
Let in het bovenstaande programma op de verklaring
numbers.reduce(4, (k, v) -> v, (v1, v2) -> v1+v2);
Hier,
- 4 is een parallelle drempel
- (k, v) -> v is een transformatorfunctie. Het zet de sleutel/waarde-toewijzingen alleen in waarden over.
- (v1, v2) -> v1+v2 is een reduceerfunctie. Het verzamelt alle waarden en voegt alle waarden toe.
Varianten van de methode reduce()
reduceEntries()
- retourneert het resultaat van het verzamelen van alle items met behulp van de gespecificeerde reducer-functiereduceKeys()
- geeft het resultaat terug van het verzamelen van alle sleutels met behulp van de gespecificeerde reducerfunctiereduceValues()
- geeft het resultaat terug van het verzamelen van alle waarden met behulp van de gespecificeerde reducer-functie
ConcurrentHashMap versus HashMap
Hier zijn enkele van de verschillen tussen ConcurrentHashMap
en HashMap,
ConcurrentHashMap
is een thread-safe verzameling. Dat wil zeggen dat meerdere threads het tegelijkertijd kunnen openen en wijzigen.ConcurrentHashMap
biedt methoden voor bulkbewerkingen zoalsforEach()
,search()
enreduce()
.
Waarom ConcurrentHashMap?
- De
ConcurrentHashMap
class staat toe dat meerdere threads tegelijkertijd toegang hebben tot de items. - Standaard is de gelijktijdige hashmap verdeeld in 16 segmenten . Dit is de reden waarom 16 threads tegelijkertijd de kaart mogen wijzigen. Een willekeurig aantal threads heeft echter tegelijkertijd toegang tot de kaart.
- De
putIfAbsent()
methode zal de invoer op de kaart niet overschrijven als de opgegeven sleutel al bestaat. - Het biedt zijn eigen synchronisatie.
Java