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

Основной учебник Java

Java Управление потоком

Java Массив

Java Ориентированность на объекты (I)

Java Ориентированность на объекты (II)

Java Ориентированность на объекты (III)

Обработка исключений Java

Java Список (List)

Java Queue (очередь)

Java Map集合

Java Set集合

Java Вход/Вывод (I/O)

Java Reader/Writer

Другие темы Java

Java ConcurrentHashMap

В этом руководстве мы будем изучать примеры Java ConcurrentHashMap класса и его операций.

Класс ConcurrentHashMap из Java Collection Framework предоставляет безопасную для многопоточности карту. То есть, несколько потоков могут одновременно访问 эту карту, не влияя на一致性 элементов карты.

Он наследуетИнтерфейс ConcurrentMap.

Создание ConcurrentHashMap

Для создания параллельного хэш-мапа нам нужно сначала импортировать пакет java.util.concurrent.ConcurrentHashMap. После импорта пакета, мы можем создавать параллельные хэш-мапы в Java.

// ConcurrentHashMap с объемом 8 и фактором загрузки 0.6
ConcurrentHashMap<Key, Value> numbers = new ConcurrentHashMap<>(8, 0.6f);

В上面的 коде мы создали конCURRENTНУЮ хэш-карту под названием numbers.

здесь,

  • Key - уникальный идентификатор, используемый для связи каждого элемента (значения) в карте

  • Value - элемент, связанный с ключом в карте

Обратите внимание на фразу new ConcurrentHashMap<>(8, 0.6). В этом случае, первым параметром являетсяcapacity, вторым параметром являетсяloadFactor.

  • capacity - Объем этого маппинга составляет 8. Это означает, что он может хранить 8 элементов.

  • loadFactor- Фактор загрузки этой карты равен 0.6. Это означает, что как только наш хэш-таблица заполнена на 60%, элементы будут перемещены в новую хэш-таблицу, размер которой в два раза больше исходной.

Default volume and load factor

Не нужно определять его объем и фактор загрузки, чтобы создать конCURRENTНУЮ хэш-карту. Например:

// ConcurrentHashMap сdefault объемом и фактором загрузки
ConcurrentHashMap<Key, Value> numbers1 = new ConcurrentHashMap<>();

По умолчанию

  • Объем карты будет 16

  • Фактор загрузки будет 0.75

Создание ConcurrentHashMap из другого маппинга

Вот как мы создаем конCURRENTНУЮ хэш-карту, содержащую все элементы другого маппинга.

import java.util.concurrent.ConcurrentHashMap;
import java.util.HashMap;
class Main {
    public static void main(String[] args) {
        // Создание хэш-карты для четных чисел
        HashMap<String, Integer> evenNumbers = new HashMap<>();
        evenNumbers.put("Two", 2)
        evenNumbers.put("Four", 4)
        System.out.println("HashMap: " + evenNumbers);
        // Создание конCURRENTНОЙ hash-карты из другого маппинга
        ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(evenNumbers);
        numbers.put("Three", 3);
        System.out.println("ConcurrentHashMap: " + numbers);
    }
}

результат вывода

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

Методы ConcurrentHashMap

Класс ConcurrentHashMap предоставляет методы, которые позволяют нам выполнять различные операции над маппингом.

Вставка элементов в ConcurrentHashMap

  • put() - вставляет указанное значение в map

  • putAll() - вставляет все элементы из указанного mappings в этот map

  • putIfAbsent() - вставляет указанное значение в map, если ключ уже существует

например,

import java.util.concurrent.ConcurrentHashMap;
class Main {
    public static void main(String[] args) {
        //Создание ConcurrentHashMap четных чисел
        ConcurrentHashMap<String, Integer> evenNumbers = new ConcurrentHashMap<>()
        // использование put()
        evenNumbers.put("Two", 2)
        evenNumbers.put("Four", 4)
        // использование putIfAbsent()
        evenNumbers.putIfAbsent("Six", 6)
        System.out.println("КонcurrentHashMap с четными числами: " + evenNumbers)
        //Создание ConcurrentHashMap чисел
        ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
        numbers.put("One", 1);
        // использование putAll()
        numbers.putAll(evenNumbers)
        System.out.println("Числа в ConcurrentHashMap: " + numbers)
    }
}

результат вывода

КонcurrentHashMap с четными числами: {Six=6, Four=4, Two=2}
Числа в ConcurrentHashMap: {Six=6, One=1, Four=-4, Two=2}

Доступ к элементам ConcurrentHashMap

1. Использование entrySet(), keySet() и values()

  • entrySet() - возвращает коллекцию всех ключ/значение мappings

  • keySet() - возвращает коллекцию всех ключей map

  • values() - возвращает коллекцию всех значений map

например,

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);
        // 使用 entrySet()
        System.out.println("Key/Value 映射: " + numbers.entrySet())
        // 使用 keySet()
        System.out.println("Keys: " + numbers.keySet())
        // 使用 values()
        System.out.println("Значения: " + numbers.values());
    }
}

результат вывода

ConcurrentHashMap: {One=1, Two=2, Three=3}
Ключ/Значение карты: [One=1, Two=2, Three=3]
Ключи: [One, Two, Three]
Значения: [1, 2, 3]

2. Использование get() и getOrDefault()

  • get() - Возвращает значение, связанное с указанным ключом. Если ключ не найден, возвращает null.

  • getOrDefault() - Возвращает значение, связанное с указанным ключом. Если ключ не найден, возвращает указанное значение по умолчанию.

например,

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);
        // Использование get()
        int value1 = numbers.get("Three");
        System.out.println("Использование get(): " + value1);
        // Использование getOrDefault()
        int value2 = numbers.getOrDefault("Five", 5);
        System.out.println("Использование getOrDefault(): " + value2);
    }
}

результат вывода

ConcurrentHashMap: {One=1, Two=2, Three=3}
Использование get(): 3
Использование getOrDefault(): 5

Удаление элементов из ConcurrentHashMap

  • remove(key) - Возвращает и удаляет элемент из карты, связанный с указанным ключом

  • remove(key, value) - Удаляет элемент из карты, только если ключ указан и его значение равно указанному, возвращает булево значение

например,

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);
        // Метод удаления с одним параметром
        int value = numbers.remove("Two");
        System.out.println("Удаленное значение: " + value);
        // Метод удаления с двумя параметрами
        boolean result = numbers.remove("Three", 3);
        System.out.println("Элемент {Three=3} был удален? " + result);
        System.out.println("Обновленный ConcurrentHashMap: " + numbers);
    }
}

результат вывода

ConcurrentHashMap: {One=1, Two=2, Three=3}
Удаленное значение: 2
Элемент {Three=3} был удален? True
Обновленный ConcurrentHashMap: {One=1}

Методы batch-операций для ConcurrentHashMap

Класс ConcurrentHashMap предоставляет безопасные методы для параллельных batch-операций с различными map.

1. forEach()方法

1. Метод forEach()

она содержит два параметра.

  • Метод forEach()遍历 наши записи и выполняет指定的 функцию.

  • parallelismThreshold - это параметр, который specifies, после скольких элементов в мапе выполняется операция параллельно.

например,

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);
        transformer - это функция, которая преобразует данные перед передачей их в指定的 функцию.
        //forEach() не содержит переданной функции
        // forEach() передается指定的 функция
        System.out.print("Значения: ");
        numbers.forEach(4, (k, v) -> v, (v) -> System.out.print(v + ", "));
    }
}

результат вывода

ConcurrentHashMap: {One = 1, Two = 2, Three = 3}
ключ: One значение: 1
ключ: Two значение: 2
ключ: Three значение: 3
Значения: 1, 2, 3,

В上面的 программе мы использовали параметр параллельного порога4Это означает, что если в мапе содержится 4 записи, то операция выполняется параллельно.

варианты метода forEach()

  • forEachEntry() - выполняет指定的 функцию для каждой записи

  • forEachKey() - выполняет指定的 функцию для каждого ключа

  • forEachValue() - выполняет指定的 функцию для каждого значения

2. Метод search()

Метод search() ищет map по指定的 функции и возвращает соответствующие записи.

Здесь,指定的 функция определяет, что искать.

Он также содержит опциональный параметр parallelThreshold. Параметр параллельного порога specifies, после скольких элементов в мапе выполняется операция параллельно.

например,

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);
        // использовать search()
        String key = numbers.search(4, (k, v) -> {return v == 3 ? k : null;});
        System.out.println("Поисковое значение: " + key);
    }
}

результат вывода

ConcurrentHashMap: {One=1, Two=2, Three=3}
Поисковое значение: Three

варианты метода search()

  • searchEntries() - поисковая функция применяется к ключ/значению

  • searchKeys() - поисковая функция применяется только к ключам

  • searchValues() - поисковая функция применяется только к значениям

3. метод reduce()

метод reduce() накопляет (агрегирует) каждую запись в мапе. Когда нам нужны все записи для выполнения задачи (например, суммирование всех значений мапы), мы можем использовать этот метод.

она содержит два параметра.

  • parallelismThreshold - это параметр, который указывает, после скольких элементов операции в мапе будут выполняться параллельно.

  • transformer - это функция преобразования данных, которая выполняется перед передачей данных в заданную функцию.

например,

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);
        // использовать search()
        int sum = numbers.reduce(4, (k, v) -> v, (v1, v2) -> v1 + v2);
        System.out.println("Общая сумма всех значений: " + sum);
    }
}

результат вывода

ConcurrentHashMap: {One=1, Two=2, Three=3}
Общая сумма всех значений: 6

в предыдущем примере обратите внимание на следующие строки

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

здесь,

  • 4 - порог параллелизма

  • (k, v) -> v - функция преобразования. Она преобразует маппинг ключ/значение только в значение.

  • (v1, v2) -> v1+v2 - функция вычисления размера. Она собирает все значения и суммирует их.

варианты метода reduce()

  • reduceEntries() - возвращение результата сбора всех записей с использованием指定的 функции редуктора

  • reduceKeys() - возвращение результата сбора всех ключей с использованием指定的 функции редуктора

  • reduceValues() - возвращение результата сбора всех значений с использованием指定的 функции редуктора

Различия между ConcurrentHashMap и HashMap

Ниже приведены различия между ConcurrentHashMap иHashMap之间存在一些区别

  • ConcurrentHashMap являетсяТред-безопасностьСборники. То есть, несколько потоков могут одновременно доступ к ним и их модификация.

  • ConcurrentHashMap предоставляет методы для параллельных операций, таких как forEach(), search() и reduce().

Почему выбирают ConcurrentHashMap?

  • Класс ConcurrentHashMap позволяет множеству потоков выполнять параллельные операции по модификации.

  • По умолчанию, параллельные хэш-маппинги разделены16段Вот почему разрешается одновременное изменение карты 16 потоками. Но в один момент может быть доступно любое количество потоков.

  • Если指定的 ключ уже существует, то метод putIfAbsent() не будет заменять запись в маппинге.