Создание собственных аннотаций в Java
Создание собственных аннотаций позволяет добавлять метаданные к вашему коду, которые могут быть использованы компилятором, инструментами разработки или во время выполнения. Аннотации можно использовать для валидации данных, конфигурации и других задач.
Для создания аннотации используется ключевое слово @ interface.
@ Retention: Указывает, насколько долго аннотация сохраняется (например, только в исходном коде, в классе или во время выполнения).
RetentionPolicy.SOURCE: Аннотация сохраняется только в исходном коде и отбрасывается компилятором.
RetentionPolicy.CLASS: Аннотация сохраняется в файле класса, но не доступна во время выполнения.
RetentionPolicy.RUNTIME: Аннотация сохраняется во время выполнения и может быть прочитана с помощью рефлексии.
Применение собственной аннотации
Чтение аннотаций с помощью рефлексии
Методы аннотаций
Аннотации могут содержать методы, которые определяют параметры аннотации. Методы могут иметь значения по умолчанию.
Пример использования:
Ограничения и мета-аннотации
Мета-аннотации — это аннотации, которые применяются к другим аннотациям. В Java существует несколько мета-аннотаций:
@ Retention: Указывает, насколько долго аннотация сохраняется.
@ Target: Указывает, где аннотация может быть применена (например, к методам, полям, классам).
@ Inherited: Указывает, что аннотация может быть унаследована подклассами.
@ Documented: Указывает, что аннотация должна быть задокументирована с помощью javadoc.
Пример использования мета-аннотаций:
Пример практического использования собственных аннотаций
Валидация с помощью аннотаций
Создадим аннотацию для проверки полей класса:
#Java #Training #Annotation #Medium
Создание собственных аннотаций позволяет добавлять метаданные к вашему коду, которые могут быть использованы компилятором, инструментами разработки или во время выполнения. Аннотации можно использовать для валидации данных, конфигурации и других задач.
Для создания аннотации используется ключевое слово @ interface.
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomAnnotation {
String value();
int number() default 42;
}
@ Retention: Указывает, насколько долго аннотация сохраняется (например, только в исходном коде, в классе или во время выполнения).
RetentionPolicy.SOURCE: Аннотация сохраняется только в исходном коде и отбрасывается компилятором.
RetentionPolicy.CLASS: Аннотация сохраняется в файле класса, но не доступна во время выполнения.
RetentionPolicy.RUNTIME: Аннотация сохраняется во время выполнения и может быть прочитана с помощью рефлексии.
Применение собственной аннотации
@MyCustomAnnotation(value = "Example", number = 10)
public class CustomAnnotatedClass {
}
Чтение аннотаций с помощью рефлексии
import java.lang.annotation.Annotation;
public class CustomAnnotationReflection {
public static void main(String[] args) {
Class<CustomAnnotatedClass> clazz = CustomAnnotatedClass.class;
if (clazz.isAnnotationPresent(MyCustomAnnotation.class)) {
MyCustomAnnotation annotation = clazz.getAnnotation(MyCustomAnnotation.class);
System.out.println("Value: " + annotation.value());
System.out.println("Number: " + annotation.number());
}
}
}
Методы аннотаций
Аннотации могут содержать методы, которые определяют параметры аннотации. Методы могут иметь значения по умолчанию.
public @interface DetailedAnnotation {
String description();
boolean enabled() default true;
}
Пример использования:
@DetailedAnnotation(description = "This is a detailed annotation", enabled = false)
public class DetailedAnnotatedClass {
}
Ограничения и мета-аннотации
Мета-аннотации — это аннотации, которые применяются к другим аннотациям. В Java существует несколько мета-аннотаций:
@ Retention: Указывает, насколько долго аннотация сохраняется.
@ Target: Указывает, где аннотация может быть применена (например, к методам, полям, классам).
@ Inherited: Указывает, что аннотация может быть унаследована подклассами.
@ Documented: Указывает, что аннотация должна быть задокументирована с помощью javadoc.
Пример использования мета-аннотаций:
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface MultiTargetAnnotation {
String value();
}
Пример практического использования собственных аннотаций
Валидация с помощью аннотаций
Создадим аннотацию для проверки полей класса:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface NotNull {
}
Применим аннотацию к классу:
java
Копировать код
public class User {
@NotNull
private String name;
public User(String name) {
this.name = name;
}
}
#Java #Training #Annotation #Medium
Создадим метод для проверки полей:
Этот пример показывает, как создавать и использовать собственные аннотации для выполнения валидации данных. Аннотации делают код более читаемым и структурированным, позволяя легко добавлять новые проверки и конфигурации.
#Java #Training #Annotation #Medium
import java.lang.reflect.Field;
public class Validator {
public static void validate(Object object) throws IllegalAccessException {
Field[] fields = object.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(NotNull.class)) {
field.setAccessible(true);
Object value = field.get(object);
if (value == null) {
throw new IllegalArgumentException(field.getName() + " cannot be null");
}
}
}
}
public static void main(String[] args) {
User user = new User(null);
try {
validate(user);
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
Этот пример показывает, как создавать и использовать собственные аннотации для выполнения валидации данных. Аннотации делают код более читаемым и структурированным, позволяя легко добавлять новые проверки и конфигурации.
#Java #Training #Annotation #Medium
Всем доброго субботнего утра! ☀️
Как ваше настроение, какие планы на выходные?
Делитесь с нами в чате - https://t.me/Java_Beginner_chat
Напоминаю, что завтра в 16:00 по МСК запланирована онлайн встреча, где мы наконец-то закончим наше консольное TODO приложение!)))
Как ваше настроение, какие планы на выходные?
Делитесь с нами в чате - https://t.me/Java_Beginner_chat
Напоминаю, что завтра в 16:00 по МСК запланирована онлайн встреча, где мы наконец-то закончим наше консольное TODO приложение!)))
Утро программиста.
#Mems
объекты: Жена, Будильник, Автомобиль;
переменные: совесть, желание_спать, сытость, злость
если Будильник = 1
{
перевести(5min);
перевести(5min);
выключить();
встать();
}
если Будильник = 0
{
пока (совесть < желание_спать)
{
спать();
}
встать();
}
умыться();
если Жена > 0
{
приготовить_завтрак(жена);
}
если Жена = 0
{
приготовить_завтрак(содержимое холодильника[0]);
}
сытость = сытость + 1;
если автомобиль !=1
{
добраться_до_работы(спать());
}
если автомобиль =1
{
добраться_до_работы(злость);
}
#Mems
Напоминаю про канал моего товарища 3D-шника) - https://t.me/model3ddd/3511
Если вас интересует данная тема, есть желание изучить ее подробнее, ознакомиться с примерами работ - залетайте не думая!
Если вас интересует данная тема, есть желание изучить ее подробнее, ознакомиться с примерами работ - залетайте не думая!
Telegram
3Dshnik
📱 Все: мы будем использовать ChatGPT для революций в науке и технике
Мы используем ChatGPT:
3Dshnik - Подписаться
Мы используем ChatGPT:
3Dshnik - Подписаться
А вы придете на онлайн встречу в 16:00 по МСК сегодня?
Anonymous Poll
42%
Да, я буду!)
50%
Хотел бы, но не могу(
0%
Нет, нафиг мне это надо?)))
8%
Что это за канал?)
This media is not supported in your browser
VIEW IN TELEGRAM
Запись нашей сегодняшней встречи -
https://youtu.be/QGPf_ki7V1c
Огромная благодарность тем кто был, за участие и подсказки, без Вас было б скучнее))))
Мы наконец то закончили консольную записную книжку, написанную в самом простом варианте, понятном даже для новичков.
Смотрите, комментируйте, задавайте вопросы! Обязательно подписывайтесь на ютуб канал!
Гит репозиторий с результатом - https://github.com/Oleborn/Notebook
Всем лучей добра)⭐️
https://youtu.be/QGPf_ki7V1c
Огромная благодарность тем кто был, за участие и подсказки, без Вас было б скучнее))))
Мы наконец то закончили консольную записную книжку, написанную в самом простом варианте, понятном даже для новичков.
Смотрите, комментируйте, задавайте вопросы! Обязательно подписывайтесь на ютуб канал!
Гит репозиторий с результатом - https://github.com/Oleborn/Notebook
Всем лучей добра)⭐️
HashMap структура и внутреннее устройство.
HashMap — это одна из наиболее часто используемых структур данных в программировании, обеспечивающая хранение пар "ключ-значение" с возможностью быстрой вставки, удаления и поиска данных.
Основные характеристики HashMap:
Ключи и значения: Хранит пары "ключ-значение".
Хэш-функция: Использует хэш-функцию для вычисления индекса, по которому будет храниться элемент.
Бакеты: Внутренне HashMap представляет собой массив бакетов (корзин).
Связанный список или дерево в бакетах: При коллизии (когда разные ключи имеют одинаковый хэш) используется либо связанный список, либо сбалансированное дерево (в современных реализациях).
Внутреннее устройство HashMap
HashMap использует массив, где каждый элемент называется бакетом. Каждому ключу через хэш-функцию сопоставляется индекс бакета.
Бакеты
Бакет — это место для хранения пары "ключ-значение". Если несколько ключей попадают в один и тот же бакет (коллизия), они хранятся в виде связанного списка или красно-черного дерева.
Связанный список и дерево в бакетах
Когда происходит коллизия, в бакете начинается формироваться структура данных:
Связанный список: В более старых реализациях Java при коллизии использовался связанный список.
Красно-черное дерево: Начиная с Java 8, при определенном числе элементов в бакете связанный список преобразуется в красно-черное дерево для улучшения производительности.
Хэш-функция
HashMap использует метод hashCode() ключа для вычисления его хэш-кода, который затем преобразуется в индекс бакета с использованием операции побитового AND с размером массива минус один.
Алгоритм поиска
Вычисление хэш-кода: Сначала вычисляется хэш-код ключа.
Вычисление индекса бакета: Индекс вычисляется с использованием операции побитового AND.
Поиск в бакете: В бакете выполняется последовательный поиск в связанном списке или дерево-поиск, если это красно-черное дерево.
Сложность поиска
В среднем: O(1) для поиска, вставки и удаления. Это достигается благодаря равномерному распределению элементов по бакетам с использованием хорошей хэш-функции.
В худшем случае: O(n), если все ключи попадают в один бакет, и при этом используется связанный список. В случае использования красно-черного дерева сложность поиска в худшем случае будет O(log n).
Пример работы с коллизиями
В этом примере ключи 1 и 17 могут попасть в один бакет, в зависимости от размера массива и хэш-функции, что демонстрирует ситуацию с коллизией.
Полезные ссылки для более полного ознакомления с HashMap (спасибо авторам за их кропотливую работу):
https://habr.com/ru/articles/128017/
https://javarush.com/groups/posts/2496-podrobnihy-razbor-klassa-hashmap
#Java #Training #Medium #HashMap
HashMap — это одна из наиболее часто используемых структур данных в программировании, обеспечивающая хранение пар "ключ-значение" с возможностью быстрой вставки, удаления и поиска данных.
Основные характеристики HashMap:
Ключи и значения: Хранит пары "ключ-значение".
Хэш-функция: Использует хэш-функцию для вычисления индекса, по которому будет храниться элемент.
Бакеты: Внутренне HashMap представляет собой массив бакетов (корзин).
Связанный список или дерево в бакетах: При коллизии (когда разные ключи имеют одинаковый хэш) используется либо связанный список, либо сбалансированное дерево (в современных реализациях).
Внутреннее устройство HashMap
HashMap использует массив, где каждый элемент называется бакетом. Каждому ключу через хэш-функцию сопоставляется индекс бакета.
Бакеты
Бакет — это место для хранения пары "ключ-значение". Если несколько ключей попадают в один и тот же бакет (коллизия), они хранятся в виде связанного списка или красно-черного дерева.
Связанный список и дерево в бакетах
Когда происходит коллизия, в бакете начинается формироваться структура данных:
Связанный список: В более старых реализациях Java при коллизии использовался связанный список.
Красно-черное дерево: Начиная с Java 8, при определенном числе элементов в бакете связанный список преобразуется в красно-черное дерево для улучшения производительности.
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
// Вставка элементов
map.put("One", 1);
map.put("Two", 2);
map.put("Three", 3);
// Поиск элементов
System.out.println("Value for key 'Two': " + map.get("Two"));
// Удаление элемента
map.remove("One");
System.out.println("Map after removing 'One': " + map);
}
}
Хэш-функция
HashMap использует метод hashCode() ключа для вычисления его хэш-кода, который затем преобразуется в индекс бакета с использованием операции побитового AND с размером массива минус один.
Алгоритм поиска
Вычисление хэш-кода: Сначала вычисляется хэш-код ключа.
Вычисление индекса бакета: Индекс вычисляется с использованием операции побитового AND.
Поиск в бакете: В бакете выполняется последовательный поиск в связанном списке или дерево-поиск, если это красно-черное дерево.
Сложность поиска
В среднем: O(1) для поиска, вставки и удаления. Это достигается благодаря равномерному распределению элементов по бакетам с использованием хорошей хэш-функции.
В худшем случае: O(n), если все ключи попадают в один бакет, и при этом используется связанный список. В случае использования красно-черного дерева сложность поиска в худшем случае будет O(log n).
Пример работы с коллизиями
public class Main {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
// Эти два разных ключа могут дать одинаковый хэш-код
map.put(1, "One");
map.put(17, "Seventeen");
// Оба ключа будут находиться в одном бакете
System.out.println("Value for key 1: " + map.get(1));
System.out.println("Value for key 17: " + map.get(17));
}
}
В этом примере ключи 1 и 17 могут попасть в один бакет, в зависимости от размера массива и хэш-функции, что демонстрирует ситуацию с коллизией.
Полезные ссылки для более полного ознакомления с HashMap (спасибо авторам за их кропотливую работу):
https://habr.com/ru/articles/128017/
https://javarush.com/groups/posts/2496-podrobnihy-razbor-klassa-hashmap
#Java #Training #Medium #HashMap
Хабр
Структуры данных в картинках. HashMap
Приветствую вас, хабрачитатели! Продолжаю попытки визуализировать структуры данных в Java. В предыдущих сериях мы уже ознакомились с ArrayList и LinkedList , сегодня же рассмотрим HashMap. HashMap —...
Что выведет код?
#Tasks
public class ArithmeticChallenge {
public static void main(String[] args) {
int result = mysteriousArithmetic(3, 2);
System.out.println(result);
}
public static int mysteriousArithmetic(int a, int b) {
int result = 0;
for (int i = 1; i <= a; i++) {
result += (i % 2 == 0) ? (i * b) : (i + b);
}
return result;
}
}
#Tasks
Основные методы HashMap и их устройство
HashMap предоставляет множество методов для работы с парами "ключ-значение". Рассмотрим основные методы и разберем их внутреннее устройство.
1. put(K key, V value)
Метод put добавляет или обновляет значение для указанного ключа.
Устройство метода:
Вычисление хэш-кода ключа: Метод вызывает key.hashCode().
Вычисление индекса бакета: Используется побитовая операция AND с (n-1), где n - размер массива бакетов.
Поиск существующего ключа в бакете: Если ключ уже существует, значение обновляется.
Вставка новой пары в бакет: Если ключ не существует, создается новый узел и добавляется в бакет.
Пример использования:
2. get(Object key)
Метод get возвращает значение, связанное с указанным ключом.
Устройство метода:
Вычисление хэш-кода ключа: Метод вызывает key.hashCode().
Вычисление индекса бакета: Используется побитовая операция AND.
Поиск в бакете: Последовательно проверяются элементы в бакете.
Пример использования:
3. remove(Object key)
Метод remove удаляет пару "ключ-значение" по указанному ключу.
Устройство метода:
Вычисление хэш-кода ключа: Метод вызывает key.hashCode().
Вычисление индекса бакета: Используется побитовая операция AND.
Поиск и удаление: Ищется элемент в бакете и удаляется, если найден.
Пример использования:
#Java #Training #Medium #HashMap
HashMap предоставляет множество методов для работы с парами "ключ-значение". Рассмотрим основные методы и разберем их внутреннее устройство.
1. put(K key, V value)
Метод put добавляет или обновляет значение для указанного ключа.
Устройство метода:
Вычисление хэш-кода ключа: Метод вызывает key.hashCode().
Вычисление индекса бакета: Используется побитовая операция AND с (n-1), где n - размер массива бакетов.
Поиск существующего ключа в бакете: Если ключ уже существует, значение обновляется.
Вставка новой пары в бакет: Если ключ не существует, создается новый узел и добавляется в бакет.
public V put(K key, V value) {
// Вычисление хэш-кода
int hash = hash(key);
// Вычисление индекса бакета
int bucketIndex = indexFor(hash, table.length);
// Поиск существующего ключа и обновление значения
for (Entry<K, V> e = table[bucketIndex]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
return oldValue;
}
}
// Вставка новой пары ключ-значение
addEntry(hash, key, value, bucketIndex);
return null;
}
Пример использования:
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("One", 1);
map.put("Two", 2);
System.out.println(map); // Output: {One=1, Two=2}
}
}
2. get(Object key)
Метод get возвращает значение, связанное с указанным ключом.
Устройство метода:
Вычисление хэш-кода ключа: Метод вызывает key.hashCode().
Вычисление индекса бакета: Используется побитовая операция AND.
Поиск в бакете: Последовательно проверяются элементы в бакете.
public V get(Object key) {
// Вычисление хэш-кода
int hash = hash(key);
// Поиск в бакете
for (Entry<K, V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
return e.value;
}
}
return null;
}
Пример использования:
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("One", 1);
System.out.println(map.get("One")); // Output: 1
}
}
3. remove(Object key)
Метод remove удаляет пару "ключ-значение" по указанному ключу.
Устройство метода:
Вычисление хэш-кода ключа: Метод вызывает key.hashCode().
Вычисление индекса бакета: Используется побитовая операция AND.
Поиск и удаление: Ищется элемент в бакете и удаляется, если найден.
public V remove(Object key) {
Entry<K, V> e = removeEntryForKey(key);
return (e == null ? null : e.value);
}
private Entry<K, V> removeEntryForKey(Object key) {
// Вычисление хэш-кода
int hash = hash(key);
int bucketIndex = indexFor(hash, table.length);
Entry<K, V> prev = table[bucketIndex];
Entry<K, V> e = prev;
while (e != null) {
Entry<K, V> next = e.next;
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
if (prev == e) {
table[bucketIndex] = next;
} else {
prev.next = next;
}
return e;
}
prev = e;
e = next;
}
return null;
}
Пример использования:
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("One", 1);
map.put("Two", 2);
map.remove("One");
System.out.println(map); // Output: {Two=2}
}
}
#Java #Training #Medium #HashMap
4. containsKey(Object key)
Метод containsKey проверяет, существует ли указанная ключ в HashMap.
Устройство метода:
Использует метод get: Если метод get возвращает не null, значит ключ существует.
Пример использования:
5. containsValue(Object value)
Метод containsValue проверяет, существует ли указанное значение в HashMap.
Устройство метода:
Проходит по всем бакетам: Проверяет каждый элемент на наличие значения.
Пример использования:
6. size()
Метод size возвращает количество пар "ключ-значение" в HashMap.
Устройство метода:
Хранение размера: HashMap хранит размер как переменную size.
7. clear()
Метод clear удаляет все пары "ключ-значение" из HashMap.
Устройство метода:
Устанавливает массив бакетов в null: И обнуляет размер.
Пример использования:
#Java #Training #Medium #HashMap
Метод containsKey проверяет, существует ли указанная ключ в HashMap.
Устройство метода:
Использует метод get: Если метод get возвращает не null, значит ключ существует.
public boolean containsKey(Object key) {
return getEntry(key) != null;
}
final Entry<K, V> getEntry(Object key) {
// Вычисление хэш-кода
int hash = (key == null) ? 0 : hash(key);
// Поиск в бакете
for (Entry<K, V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) {
return e;
}
}
return null;
}
Пример использования:
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("One", 1);
System.out.println(map.containsKey("One")); // Output: true
System.out.println(map.containsKey("Two")); // Output: false
}
}
5. containsValue(Object value)
Метод containsValue проверяет, существует ли указанное значение в HashMap.
Устройство метода:
Проходит по всем бакетам: Проверяет каждый элемент на наличие значения.
public boolean containsValue(Object value) {
if (value == null) {
for (Entry<K, V> e : table)
for (Entry<K, V> ee = e; ee != null; ee = ee.next)
if (ee.value == null)
return true;
} else {
for (Entry<K, V> e : table)
for (Entry<K, V> ee = e; ee != null; ee = ee.next)
if (value.equals(ee.value))
return true;
}
return false;
}
Пример использования:
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("One", 1);
System.out.println(map.containsValue(1)); // Output: true
System.out.println(map.containsValue(2)); // Output: false
}
}
6. size()
Метод size возвращает количество пар "ключ-значение" в HashMap.
Устройство метода:
Хранение размера: HashMap хранит размер как переменную size.
public int size() {
return size;
}
Пример использования:
java
Копировать код
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("One", 1);
map.put("Two", 2);
System.out.println(map.size()); // Output: 2
}
}
7. clear()
Метод clear удаляет все пары "ключ-значение" из HashMap.
Устройство метода:
Устанавливает массив бакетов в null: И обнуляет размер.
public void clear() {
Entry<K, V>[] tab = table;
for (int i = 0; i < tab.length; i++)
tab[i] = null;
size = 0;
}
Пример использования:
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("One", 1);
map.put("Two", 2);
map.clear();
System.out.println(map.size()); // Output: 0
}
}
#Java #Training #Medium #HashMap
ConcurrentHashMap, отличие от HashMap
ConcurrentHashMap — это класс в пакете java.util.concurrent, который представляет собой потокобезопасную версию HashMap. Он разработан для использования в многопоточных приложениях, где необходимо гарантировать корректность и производительность при одновременном доступе к коллекции из нескольких потоков.
Основные характеристики ConcurrentHashMap
Потокобезопасность: ConcurrentHashMap реализует эффективные механизмы блокировок для обеспечения потокобезопасного доступа к данным. В отличие от Hashtable, который синхронизирует все методы, ConcurrentHashMap использует более изящные механизмы управления доступом.
Производительность: За счет использования сегментации (в старых версиях) или уменьшенных блокировок (в новых версиях), ConcurrentHashMap обеспечивает высокую производительность в условиях многопоточного доступа.
Структура ConcurrentHashMap
Сегментация (в старых версиях): В старых версиях ConcurrentHashMap использовалась сегментация, при которой таблица хешей разбивалась на сегменты, каждый из которых был самостоятельной хеш-таблицей с собственной блокировкой. Это позволяло одновременно выполнять операции в разных сегментах без конфликтов.
Lock Striping (в новых версиях): В новых версиях ConcurrentHashMap используется механизм Lock Striping, который включает в себя более мелкие блокировки на уровне бакетов или групп бакетов, что снижает вероятность блокировок и увеличивает производительность.
Отличия ConcurrentHashMap от HashMap
Потокобезопасность: HashMap не является потокобезопасным. При одновременном доступе нескольких потоков к HashMap могут возникнуть состояния гонки и непредсказуемое поведение. В отличие от этого, ConcurrentHashMap специально разработан для безопасного использования в многопоточной среде.
Блокировки: HashMap не использует блокировки, что делает его небезопасным для многопоточного использования. ConcurrentHashMap, напротив, использует сегментацию или мелкие блокировки, что позволяет безопасно выполнять параллельные операции.
Производительность: В условиях многопоточного доступа HashMap может демонстрировать низкую производительность и некорректное поведение. ConcurrentHashMap оптимизирован для многопоточного доступа и обеспечивает более высокую производительность за счет эффективного управления блокировками.
Методы атомарных операций: ConcurrentHashMap предоставляет методы атомарных операций, такие как putIfAbsent, remove с проверкой значения и replace, которые отсутствуют в HashMap.
Пример использования ConcurrentHashMap
Полезные ссылки для более полного ознакомления с ConcurrentHashMap (спасибо авторам за их кропотливую работу):
https://habr.com/ru/articles/132884/
https://www.baeldung.com/java-concurrent-map
#Java #Training #Medium #ConcurrentHashMap
ConcurrentHashMap — это класс в пакете java.util.concurrent, который представляет собой потокобезопасную версию HashMap. Он разработан для использования в многопоточных приложениях, где необходимо гарантировать корректность и производительность при одновременном доступе к коллекции из нескольких потоков.
Основные характеристики ConcurrentHashMap
Потокобезопасность: ConcurrentHashMap реализует эффективные механизмы блокировок для обеспечения потокобезопасного доступа к данным. В отличие от Hashtable, который синхронизирует все методы, ConcurrentHashMap использует более изящные механизмы управления доступом.
Производительность: За счет использования сегментации (в старых версиях) или уменьшенных блокировок (в новых версиях), ConcurrentHashMap обеспечивает высокую производительность в условиях многопоточного доступа.
Структура ConcurrentHashMap
Сегментация (в старых версиях): В старых версиях ConcurrentHashMap использовалась сегментация, при которой таблица хешей разбивалась на сегменты, каждый из которых был самостоятельной хеш-таблицей с собственной блокировкой. Это позволяло одновременно выполнять операции в разных сегментах без конфликтов.
Lock Striping (в новых версиях): В новых версиях ConcurrentHashMap используется механизм Lock Striping, который включает в себя более мелкие блокировки на уровне бакетов или групп бакетов, что снижает вероятность блокировок и увеличивает производительность.
Отличия ConcurrentHashMap от HashMap
Потокобезопасность: HashMap не является потокобезопасным. При одновременном доступе нескольких потоков к HashMap могут возникнуть состояния гонки и непредсказуемое поведение. В отличие от этого, ConcurrentHashMap специально разработан для безопасного использования в многопоточной среде.
Блокировки: HashMap не использует блокировки, что делает его небезопасным для многопоточного использования. ConcurrentHashMap, напротив, использует сегментацию или мелкие блокировки, что позволяет безопасно выполнять параллельные операции.
Производительность: В условиях многопоточного доступа HashMap может демонстрировать низкую производительность и некорректное поведение. ConcurrentHashMap оптимизирован для многопоточного доступа и обеспечивает более высокую производительность за счет эффективного управления блокировками.
Методы атомарных операций: ConcurrentHashMap предоставляет методы атомарных операций, такие как putIfAbsent, remove с проверкой значения и replace, которые отсутствуют в HashMap.
Пример использования ConcurrentHashMap
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;
public class ConcurrentHashMapExample {
public static void main(String[] args) {
// Создание ConcurrentHashMap
Map<String, Integer> map = new ConcurrentHashMap<>();
// Добавление элементов
map.put("Apple", 50);
map.put("Banana", 30);
map.put("Orange", 20);
// Получение значения по ключу
System.out.println("Price of Apple: " + map.get("Apple"));
// Проверка наличия ключа
if (map.containsKey("Banana")) {
System.out.println("Banana is in the list.");
}
// Удаление элемента
map.remove("Orange");
// Перебор элементов
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// Использование атомарных операций
map.putIfAbsent("Grapes", 40);
map.replace("Banana", 35);
// Перебор элементов после атомарных операций
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
}
Полезные ссылки для более полного ознакомления с ConcurrentHashMap (спасибо авторам за их кропотливую работу):
https://habr.com/ru/articles/132884/
https://www.baeldung.com/java-concurrent-map
#Java #Training #Medium #ConcurrentHashMap
Baeldung
A Guide to ConcurrentMap | Baeldung
A quick and practical guide to ConcurrentMap in Java.
Как вы относитесь к тому, что посты иногда разорваны? (Это из-за большого объема информации)
Anonymous Poll
67%
Все нормально
17%
Очень неудобно читать
17%
Без разницы
Что выведет код?
#Tasks
import java.util.HashMap;
import java.util.Map;
public class HashMapChallenge {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("one", 1);
map.put("two", 2);
map.put("three", 3);
map.put("four", 4);
int result = processMap(map);
System.out.println(result);
}
public static int processMap(Map<String, Integer> map) {
int sum = 0;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getKey().length() % 2 == 0) {
sum += entry.getValue() * 2;
} else {
sum += entry.getValue() * 3;
}
}
return sum;
}
}
#Tasks