English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Tutoriales básicos de Java

Java 流程控制

Java 数组

Java 面向对象(I)

Java 面向对象(II)

Java 面向对象(III)

Manejo de excepciones en Java

Java 列表(List)

Java Queue(队列)

Java Map集合

Java Set集合

Java 输入输出(I)/O)

Java Reader/Writer

Java 其他主题

Java ConcurrentHashMap

在本教程中,我们将借助示例学习Java ConcurrentHashMap类及其操作。

Java集合框架的ConcurrentHashMap类提供了线程安全的映射。也就是说,多个线程可以一次访问该映射,而不会影响映射中条目的一致性。

它继承了ConcurrentMap接口

创建一个ConcurrentHashMap

为了创建并发的哈希图,我们必须先导入java.util.concurrent.ConcurrentHashMap包。导入包后,就可以在Java中创建并发哈希映射。

//ConcurrentHashMap具有容量8和负载因子0.6
ConcurrentHashMap<Key, Value> numbers = new ConcurrentHashMap<>(8, 0.6f);

在上面的代码中,我们创建了一个名为numbers的并发哈希映射。

aquí,

  • Clave - 用于关联map中每个元素(值)的唯一标识符

  • Value - map中与键相关联的元素

注意语句 new ConcurrentHashMap<>(8, 0.6)。在这里,第一个参数是capacity,第二个参数是loadFactor

  • capacity -该映射的容量为8。意味着,它可以存储8个条目。

  • loadFactor-此map的负载因子为0.6。这意味着,只要我们的哈希表填充了60%,条目就会移到新哈希表中,其大小是原始哈希表的两倍。

默认容量和负载因子

无需定义其容量和负载因子就可以创建并发哈希图。例如,

// 具有默认容量和负载因子的ConcurrentHashMap
ConcurrentHashMap<Key, Value> numbers1 = new ConcurrentHashMap<>();

Por defecto,

  • La capacidad del map será 16

  • El factor de carga será 0.75

Crear ConcurrentHashMap desde otro mapeo

Así es como creamos un ConcurrentHashMap que contiene todos los elementos de otro mapeo.

import java.util.concurrent.ConcurrentHashMap;
import java.util.HashMap;
class Main {
    public static void main(String[] args) {
        // Crear HashMap par
        HashMap<String, Integer> evenNumbers = new HashMap<>();
        evenNumbers.put("Two", 2);
        evenNumbers.put("Four", 4);
        System.out.println("HashMap: ", + evenNumbers);
        //Crear ConcurrentHashMap desde otro mapeo
        ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(evenNumbers);
        numbers.put("Three", 3);
        System.out.println("ConcurrentHashMap: " + numbers);
    }
}

Resultados de salida

HashMap: {Four=4, Two=2}
ConcurrentHashMap: {Four=4, Two=2, Three=3}

Métodos de ConcurrentHashMap

La clase ConcurrentHashMap proporciona métodos que nos permiten realizar varias operaciones en el mapeo.

Insertar el elemento en ConcurrentHashMap

  • put() - Insertar la clave especificada/Insertar valores mapeados en el mapeo

  • putAll() - Insertar todos los elementos del mapeo especificado en este map

  • putIfAbsent() - Si el mapeo no contiene la clave especificada, insertar la clave especificada/Insertar valores mapeados en el map

por ejemplo,

import java.util.concurrent.ConcurrentHashMap;
class Main {
    public static void main(String[] args) {
        //Creando ConcurrentHashMap par
        ConcurrentHashMap<String, Integer> evenNumbers = new ConcurrentHashMap<>();
        // Usando put()
        evenNumbers.put("Two", 2);
        evenNumbers.put("Four", 4);
        // Usando putIfAbsent()
        evenNumbers.putIfAbsent("Six", 6);
        System.out.println("El ConcurrentHashMap par: ", + evenNumbers);
        //Creando ConcurrentHashMap de números
        ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
        numbers.put("One", 1);
        // Usando putAll()
        numbers.putAll(evenNumbers);
        System.out.println("El ConcurrentHashMap de números: ", + numbers);
    }
}

Resultados de salida

El ConcurrentHashMap par: {Six=6, Four=4, Two=2}
ConcurrentHashMap de números: {Six=6, One=1, Four=-4, Two=2}

acceder a los elementos de ConcurrentHashMap

1.usando entrySet(), keySet() y values()

  • entrySet() - devuelve un conjunto de todas las claves/colección del mapeo de valores

  • keySet() - devuelve la colección de todas las claves del mapa

  • values() - devuelve la colección de todos los valores del mapa

por ejemplo,

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);
        // usando entrySet()
        System.out.println("Clave/Mapa de valores: + numbers.entrySet());
        // usando keySet()
        System.out.println("Claves: ") + numbers.keySet());
        // usando values()
        System.out.println("Valores: ") + numbers.values());
    }
}

Resultados de salida

ConcurrentHashMap: {One=1, Two=2, Three=3}
Clave/Mapa de valores: [One=1, Two=2, Three=3]
Claves: [One, Two, Three]
Valores: [1, 2, 3]

2.usando get() y getOrDefault()

  • get() - devuelve el valor asociado con la clave especificada. Si no se encuentra la clave, devuelve null.

  • getOrDefault() - devuelve el valor asociado con la clave especificada. Si no se encuentra la clave, devuelve el valor de predeterminado especificado.

por ejemplo,

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);
        // usando get()
        int value1 = numbers.get("Three");
        System.out.println("usando get(): " + value1);
        // usando getOrDefault()
        int value2 = numbers.getOrDefault("Five", 5);
        System.out.println("usando getOrDefault(): " + value2);
    }
}

Resultados de salida

ConcurrentHashMap: {One=1, Two=2, Three=3}
usando get(): 3
usando getOrDefault(): 5

eliminar elementos de ConcurrentHashMap

  • remove(key) - devuelve y elimina la entrada asociada con la clave especificada de la tabla de mapeo

  • remove(key, value) - sólo se elimina la entrada de la tabla de mapeo cuando la clave está mapeada al valor especificado y se devuelve un valor booleano

por ejemplo,

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);
        //método de eliminación con un solo parámetro
        int value = numbers.remove("Two");
        System.out.println("Valor eliminado: " + value);
        // método de eliminación con dos parámetros
        boolean result = numbers.remove("Three", 3);
        System.out.println("Entrada {Three=3} ¿Fue eliminado? " + result);
        System.out.println("ConcurrentHashMap actualizado: ", + numbers);
    }
}

Resultados de salida

ConcurrentHashMap: {One=1, Two=2, Three=3}
Valor eliminado: 2
Entrada {Three=3} ¿Fue eliminado? True
ConcurrentHashMap actualizado: {One=1}

Métodos de operaciones en lotes de ConcurrentHashMap

La clase ConcurrentHashMap proporciona métodos de batch operativos que se pueden aplicar de manera segura a diferentes mapas paralelos.

1. método forEach()

El método forEach() recorre nuestras entradas y ejecuta la función especificada.

contiene dos parámetros.

  • parallelismThreshold -Especifica cuántos elementos de la operación se ejecutarán en paralelo en el mapeo.

  • transformer -Esto convertirá los datos antes de pasarlos a la función especificada.

por ejemplo,

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() no contiene la función transmitida
        numbers.forEach(4, (k, v) -> System.out.println("clave: ", + k + " valor: " + v));
        // forEach() pasa la función especificada
        System.out.print("Los valores son ");
        numbers.forEach(4, (k, v) -> v, (v) -> System.out.print(v + , ");
    }
}

Resultados de salida

ConcurrentHashMap: {One = 1, Two = 2, Three = 3}
clave: One valor: 1
clave: Two valor: 2
clave: Three valor: 3
Los valores son 1, 2, 3,

En el programa anterior, utilizamos el umbral de paralelismo4. Esto significa que, si el map contiene4operación se ejecutará en paralelo.

Variantes del método forEach()

  • forEachEntry() - Ejecuta la función especificada para cada entrada

  • forEachKey() - Ejecuta la función especificada para cada clave

  • forEachValue() - Ejecuta la función especificada para cada valor

2. search() método

El método search() busca en el map basado en la función especificada y devuelve la entrada coincidente.

Aquí, la función especificada determina qué entrada buscar.

Además, contiene un parámetro opcional parallelThreshold. El umbral de paralelismo especifica cuántos elementos en el mapeo deben existir antes de ejecutar la operación en paralelo.

por ejemplo,

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);
        // usando search()
        String key = numbers.search(4, (k, v) -> {return v == 3 ? k: null;});
        System.out.println("Valor buscado: ", + key);
    }
}

Resultados de salida

ConcurrentHashMap: {One=1, Two=2, Three=3}
valor a buscar: Three

variante del método search()

  • searchEntries() - la función de búsqueda se aplica a las claves/mapeo de valores

  • searchKeys() - la función de búsqueda se aplica solo a las claves

  • searchValues() - la función de búsqueda se aplica solo a los valores

3. reduce() método

El método reduce() acumula (agrega) cada entrada en el mapeo. Cuando necesitemos todos los elementos para ejecutar una tarea común (por ejemplo, agregar todos los valores del mapeo), podemos usar este método.

contiene dos parámetros.

  • parallelismThreshold -especifica cuántos elementos después, la operación en el map se ejecutará en paralelo.

  • transformer - esto convertirá los datos antes de que se pasen al función especificada

por ejemplo,

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);
        // usando search()
        int sum = numbers.reduce(4, (k, v) -> v, (v1, v2) -> v1 + v2);
        System.out.println("La suma total de todos los valores: " + sum);
    }
}

Resultados de salida

ConcurrentHashMap: {One=1, Two=2, Three=3}
La suma total de todos los valores: 6

En el programa anterior, preste atención a las siguientes instrucciones

numbers.reduce(4, (k, v) -> v, (v1, v2) -> v1+v2);

aquí,

  • 4 es el umbral paralelo

  • (k, v) -> v es una función de conversión. Transforma las claves/la mapeo de valores se convierte solo en valores.

  • (v1, v2) -> v1+v2 es una función de cálculo de tamaño. Recolecta todos los valores y los suma.

variante del método reduce()

  • reduceEntries() - devuelve el resultado de recopilar todos los elementos utilizando la función reducer especificada

  • reduceKeys() - devuelve el resultado de recopilar todos los valores utilizando la función reducer especificada

  • reduceValues() - devuelve el resultado de recopilar todos los valores utilizando la función reductora especificada

diferencias entre ConcurrentHashMap y HashMap

A continuación se muestra la diferencia entre ConcurrentHashMap yHashMapdiferencias entre

  • ConcurrentHashMap es线程安全的conjuntos. Es decir, varios hilos pueden acceder y modificarlo simultáneamente.

  • ConcurrentHashMap proporciona métodos para operaciones en lote, como forEach(), search() y reduce().

¿Por qué elegir ConcurrentHashMap?

  • La clase ConcurrentHashMap permite que varias operaciones de modificación se realicen de manera concurrente por varios hilos.

  • Por defecto, el ConcurrentHashMap se divide en16段por lo que se permite16razones para que varias hilos puedan modificar el mapeo simultáneamente. Sin embargo, se puede acceder a cualquier cantidad de hilos a la vez.

  • El método putIfAbsent() no sobrescribirá la entrada en el mapeo si la clave ya existe.