Освоение Java ConcurrentHashMap: операции, примеры и лучшие практики
Java ConcurrentHashMap
Изучите класс Java ConcurrentHashMap, научитесь создавать и манипулировать им, и откройте его ключевые преимущества с практическими примерами кода.
Класс ConcurrentHashMap из Java Collections Framework предлагает потокобезопасную реализацию карты. Несколько потоков могут одновременно читать и писать без повреждения целостности карты.
Он реализует интерфейс ConcurrentMap и является частью java.util.concurrent.
Создание ConcurrentHashMap
Сначала импортируйте класс:
import java.util.concurrent.ConcurrentHashMap;
Затем создайте экземпляр. Можно указать начальную ёмкость и коэффициент загрузки, или положиться на значения по умолчанию.
// Ёмкость 8, коэффициент загрузки 0.6
ConcurrentHashMap<Key, Value> numbers = new ConcurrentHashMap<>(8, 0.6f);
Параметры
capacity— начальное количество корзин (8 в примере).loadFactor— запускает ресайз, когда карта достигает 60% заполненности.
Конструктор по умолчанию создаёт карту с ёмкостью 16 и коэффициентом загрузки 0.75:
ConcurrentHashMap<Key, Value> numbers1 = new ConcurrentHashMap<>();
Создание ConcurrentHashMap из существующих карт
Можно заполнить новый ConcurrentHashMap записями любой другой карты.
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);
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
Вставка элементов
put(K key, V value)— добавляет или заменяет отображение.putAll(Map<? extends K, ? extends V> m)— массовая вставка.putIfAbsent(K key, V value)— вставляет только если ключ отсутствует.
ConcurrentHashMap<String, Integer> evenNumbers = new ConcurrentHashMap<>();
evenNumbers.put("Two", 2);
evenNumbers.put("Four", 4);
evenNumbers.putIfAbsent("Six", 6);
System.out.println("Even numbers: " + evenNumbers);
ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
numbers.put("One", 1);
numbers.putAll(evenNumbers);
System.out.println("Numbers: " + numbers);
Вывод
Even numbers: {Six=6, Four=4, Two=2} Numbers: {Six=6, One=1, Four=4, Two=2}
Доступ к элементам
Используйте представления коллекций или методы получения ключ/значение.
entrySet(),keySet(),values()— возвращают коллекции записей, ключей или значений.get(K key)— получает значение илиnull, если отсутствует.getOrDefault(K key, V defaultValue)— получает значение или предоставленное по умолчанию.
ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
System.out.println("Map: " + numbers);
System.out.println("Entries: " + numbers.entrySet());
System.out.println("Keys: " + numbers.keySet());
System.out.println("Values: " + numbers.values());
int val = numbers.get("Three");
System.out.println("get(\"Three\"): " + val);
int def = numbers.getOrDefault("Five", 5);
System.out.println("getOrDefault(\"Five\", 5): " + def);
Вывод
Map: {One=1, Two=2, Three=3} Entries: [One=1, Two=2, Three=3] Keys: [One, Two, Three] Values: [1, 2, 3] get("Three"): 3 getOrDefault("Five", 5): 5
Удаление записей
remove(K key)— удаляет отображение и возвращает его значение.remove(K key, V value)— удаляет только если текущее значение совпадает; возвращает boolean.
ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
int removed = numbers.remove("Two");
System.out.println("Removed value: " + removed);
boolean deleted = numbers.remove("Three", 3);
System.out.println("Entry {Three=3} removed? " + deleted);
System.out.println("Updated map: " + numbers);
Вывод
Removed value: 2 Entry {Three=3} removed? true Updated map: {One=1}
Массовые операции
Эти методы используют параллелизм для эффективной обработки больших карт.
forEach()
Итерирует по записям, опционально в параллели, и применяет consumer.
numbers.forEach(4, (k, v) -> System.out.println("key: " + k + " value: " + v));
// С трансформером:
numbers.forEach(4, (k, v) -> v, (v) -> System.out.print(v + ", "));
Здесь 4 — порог параллелизма — когда в карте минимум 4 элемента, операция может выполняться параллельно.
search()
Находит запись, удовлетворяющую предикату. Возвращает первое совпадение.
String key = numbers.search(4, (k, v) -> v == 3 ? k : null);
System.out.println("Searched key: " + key);
reduce()
Агрегирует значения с помощью редуктора. Полезно для сумм, произведений или пользовательских накоплений.
int sum = numbers.reduce(4, (k, v) -> v, (v1, v2) -> v1 + v2);
System.out.println("Sum of values: " + sum);
ConcurrentHashMap против HashMap
- Потокобезопасность —
ConcurrentHashMapпозволяет безопасные параллельные модификации;HashMapне потокобезопасен. - Массовые методы —
ConcurrentHashMapпредлагаетforEach,searchиreduceдля параллельной обработки.
Зачем использовать ConcurrentHashMap?
- Поддерживает высокую параллельность с минимальной блокировкой.
- Внутренне разделён на 16 сегментов, позволяя до 16 потокам модифицировать разные сегменты одновременно.
- Операции вроде
putIfAbsentпредотвращают случайные перезаписи. - Встроенная синхронизация устраняет необходимость во внешних блокировках.
java
- Освоение операторов Java: типы, синтаксис и практические примеры
- Комментарии в Java: типы, использование и лучшие практики
- Освоение улучшенного цикла for в Java: синтаксис, примеры и лучшие практики
- Освоение строк в Java: создание, методы и лучшие практики
- Интерфейсы в Java: концепции, реализация и лучшие практики
- Анонимные внутренние классы в Java: определение, синтаксис и практические примеры
- Try-with-resources в Java: автоматическое управление ресурсами
- Аннотации в Java: типы, размещение и практические примеры
- Assertions в Java: практическое руководство по обнаружению багов и обеспечению надежности кода
- Освоение алгоритмов Java Collections: сортировка, перемешивание и многое другое