Java ConcurrentHashMap
Java ConcurrentHashMap
Neste tutorial, aprenderemos sobre a classe Java ConcurrentHashMap e suas operações com a ajuda de exemplos.
O
ConcurrentHashMap
classe da estrutura de coleções Java fornece um mapa thread-safe. Ou seja, vários encadeamentos podem acessar o mapa de uma vez sem afetar a consistência das entradas em um mapa. Ele implementa a interface ConcurrentMap.
Criar um ConcurrentHashMap
Para criar um hashmap simultâneo, devemos importar o
java.util.concurrent.ConcurrentHashMap
pacote primeiro. Depois de importar o pacote, veja como podemos criar hashmaps simultâneos em Java.
// ConcurrentHashMap with capacity 8 and load factor 0.6
ConcurrentHashMap<Key, Value> numbers = new ConcurrentHashMap<>(8, 0.6f);
No código acima, criamos um hashmap concorrente chamado numbers .
Aqui,
- Chave - um identificador único usado para associar cada elemento (valor) em um mapa
- Valor - elementos associados por chaves em um mapa
Observe a parte
new ConcurrentHashMap<>(8, 0.6)
. Aqui, o primeiro parâmetro é capacidade e o segundo parâmetro é loadFactor . - capacidade - A capacidade deste mapa é 8. Ou seja, pode armazenar 8 entradas.
- loadFactor - O fator de carga deste mapa é 0,6. Isso significa que, sempre que nossa tabela de hash for preenchida em 60%, as entradas serão movidas para uma nova tabela de hash com o dobro do tamanho da tabela de hash original.
Capacidade e fator de carga padrão
É possível criar um hashmap simultâneo sem definir sua capacidade e fator de carga. Por exemplo,
// ConcurrentHashMap with default capacity and load factor
ConcurrentHashMap<Key, Value> numbers1 = new ConcurrentHashMap<>();
Por padrão,
- a capacidade do mapa será de 16
- o fator de carga será de 0,75
Criando ConcurrentHashMap de outros mapas
Aqui está como podemos criar um hashmap concorrente contendo todos os elementos de outros 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<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);
}
}
Saída
HashMap: {Four=4, Two=2} ConcurrentHashMap: {Four=4, Two=2, Three=3}
Métodos de ConcurrentHashMap
O
ConcurrentHashMap
classe fornece métodos que nos permitem realizar várias operações no mapa. Inserir elementos no ConcurrentHashMap
put()
- insere o mapeamento de chave/valor especificado no mapaputAll()
- insere todas as entradas do mapa especificado para este mapaputIfAbsent()
- insere o mapeamento de chave/valor especificado no mapa se a chave especificada não estiver presente no mapa
Por exemplo,
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);
}
}
Saída
ConcurrentHashMap of even numbers: {Six=6, Four=4, Two=2} ConcurrentHashMap of numbers: {Six=6, One=1, Four=-4, Two=2}
Acessar elementos do ConcurrentHashMap
1. Usando entrySet(), keySet() e values()
entrySet()
- retorna um conjunto de todos os mapeamentos de chave/valor do mapakeySet()
- retorna um conjunto de todas as chaves do mapavalues()
- retorna um conjunto de todos os valores do mapa
Por exemplo,
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());
}
}
Saída
ConcurrentHashMap: {One=1, Two=2, Three=3} Key/Value mappings: [One=1, Two=2, Three=3] Keys: [One, Two, Three] Values: [1, 2, 3]
2. Usando get() e getOrDefault()
get()
- Retorna o valor associado à chave especificada. Retornanull
se a chave não for encontrada.getOrDefault()
- Retorna o valor associado à chave especificada. Retorna o valor padrão especificado se a chave não for encontrada.
Por exemplo,
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);
}
}
Saída
ConcurrentHashMap: {One=1, Two=2, Three=3} Using get(): 3 Using getOrDefault(): 5
Remover elementos ConcurrentHashMap
remove(key)
- retorna e remove a entrada associada à chave especificada do maparemove(key, value)
- remove a entrada do mapa somente se a chave especificada for mapeada para o valor especificado e retornar um valor booleano
Por exemplo,
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);
}
}
Saída
ConcurrentHashMap: {One=1, Two=2, Three=3} Removed value: 2 Is the entry {Three=3} removed? True Updated ConcurrentHashMap: {One=1}
Operações em massa do ConcurrentHashMap
O
ConcurrentHashMap
A classe fornece diferentes operações em massa que podem ser aplicadas com segurança a mapas simultâneos. 1. Método forEach()
O
forEach()
O método itera sobre nossas entradas e executa a função especificada. Inclui dois parâmetros.
- ParallelismThreshold - Especifica que após quantos elementos as operações em um mapa são executadas em paralelo.
- transformador - Isso transformará os dados antes que os dados sejam passados para a função especificada.
Por exemplo,
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 + ", "));
}
}
Saída
ConcurrentHashMap: {One = 1, Two = 2, Three = 3} key: One value: 1 key: Two value: 2 key: Three value: 3 Values are 1, 2, 3,
No programa acima, usamos o limite paralelo 4 . Isso significa que se o mapa contiver 4 entradas, a operação será executada em paralelo.
Variação do método forEach()
forEachEntry()
- executa a função especificada para cada entradaforEachKey()
- executa a função especificada para cada teclaforEachValue()
- executa a função especificada para cada valor
2. método search()
O
search()
O método pesquisa o mapa com base na função especificada e retorna a entrada correspondente. Aqui, a função especificada determina qual entrada deve ser pesquisada.
Também inclui um parâmetro opcional parallelThreshold . O limite paralelo especifica que após quantos elementos no mapa a operação é executada em paralelo.
Por exemplo,
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);
}
}
Saída
ConcurrentHashMap: {One=1, Two=2, Three=3} Searched value: Three
Variantes do método search()
searchEntries()
- a função de pesquisa é aplicada a mapeamentos de chave/valorsearchKeys()
- a função de pesquisa é aplicada apenas às teclassearchValues()
- a função de pesquisa é aplicada apenas aos valores
3. Método reduce()
O
reduce()
método acumula (reúne) cada entrada em um mapa. Isso pode ser usado quando precisamos de todas as entradas para realizar uma tarefa comum, como adicionar todos os valores de um mapa. Inclui dois parâmetros.
- ParallelismThreshold - Especifica que após quantos elementos, as operações em um mapa são executadas em paralelo.
- transformador - Isso transformará os dados antes que os dados sejam passados para a função especificada.
Por exemplo,
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);
}
}
Saída
ConcurrentHashMap: {One=1, Two=2, Three=3} Sum of all values: 6
No programa acima, observe a declaração
numbers.reduce(4, (k, v) -> v, (v1, v2) -> v1+v2);
Aqui,
- 4 é um limite paralelo
- (k, v) -> v é uma função transformadora. Ele transfere os mapeamentos de chave/valor apenas para valores.
- (v1, v2) -> v1+v2 é uma função redutora. Ele reúne todos os valores e adiciona todos os valores.
Variantes do método reduce()
reduceEntries()
- retorna o resultado da coleta de todas as entradas usando a função redutora especificadareduceKeys()
- retorna o resultado da coleta de todas as chaves usando a função redutora especificadareduceValues()
- retorna o resultado da coleta de todos os valores usando a função redutora especificada
ConcurrentHashMap vs HashMap
Aqui estão algumas das diferenças entre
ConcurrentHashMap
e HashMap, ConcurrentHashMap
é um segmento seguro coleção. Ou seja, vários threads podem acessá-lo e modificá-lo ao mesmo tempo.ConcurrentHashMap
fornece métodos para operações em massa comoforEach()
,search()
ereduce()
.
Por que ConcurrentHashMap?
- O
ConcurrentHashMap
class permite que vários threads acessem suas entradas simultaneamente. - Por padrão, o hashmap simultâneo é dividido em 16 segmentos . Esta é a razão pela qual 16 threads podem modificar simultaneamente o mapa ao mesmo tempo. No entanto, qualquer número de threads pode acessar o mapa por vez.
- O
putIfAbsent()
O método não substituirá a entrada no mapa se a chave especificada já existir. - Ele fornece sua própria sincronização.
Java