Перейти к основному содержимому

Удалить запись из Java HashMap

· 3 мин. чтения

1. Обзор

В этой статье мы обсудим различные способы удаления записи из Java HashMap .

2. Введение

HashMap хранит записи в парах (Key, Value) с уникальными ключами. Таким образом, одной из идей было бы использование ключа в качестве идентификатора для удаления связанной записи с карты.

Мы можем использовать методы, предоставляемые интерфейсом java.util.Map , для удаления записи, используя ключ в качестве входных данных.

2.1. Использование метода удаления (ключ объекта)

Давайте попробуем это на простом примере. У нас есть карта, которая связывает продукты питания с типами продуктов:

HashMap<String, String> foodItemTypeMap = new HashMap<>();
foodItemTypeMap.put("Apple", "Fruit");
foodItemTypeMap.put("Grape", "Fruit");
foodItemTypeMap.put("Mango", "Fruit");
foodItemTypeMap.put("Carrot", "Vegetable");
foodItemTypeMap.put("Potato", "Vegetable");
foodItemTypeMap.put("Spinach", "Vegetable");

Удалим запись с ключом «Apple»:

foodItemTypeMap.remove("Apple");
// Current Map Status: {Potato=Vegetable, Carrot=Vegetable, Grape=Fruit, Mango=Fruit, Spinach=Vegetable}

2.2. Использование метода удаления (ключ объекта, значение объекта)

Это вариант первого метода, который принимает как ключ, так и значение в качестве входных данных. Мы используем этот метод в случае, если мы хотим удалить запись только в том случае, если ключ сопоставлен с определенным значением .

В foodItemTypeMap ключ «Виноград» не сопоставляется со значением «Овощ».

В результате следующая операция не приведет к каким-либо обновлениям:

foodItemTypeMap.remove("Grape", "Vegetable");
// Current Map Status: {Potato=Vegetable, Carrot=Vegetable, Grape=Fruit, Mango=Fruit, Spinach=Vegetable}

Теперь давайте рассмотрим другие сценарии удаления записи в HashMap .

3. Удаление записи во время итерации

Класс HashMap не синхронизирован . Если мы попытаемся одновременно добавить или удалить запись, это может привести к ConcurrentModificationException . Поэтому нам нужно синхронизировать операцию удаления извне .

3.1. Синхронизация с внешним объектом

Один из подходов заключается в синхронизации объекта, который инкапсулирует HashMap . Например, мы можем использовать метод entrySet () интерфейса java.util.Map для получения набора записей в HashMap . Возвращенный набор поддерживается соответствующей картой.

Таким образом, любая структурная модификация Набора также приведет к обновлению Карты .

Давайте удалим запись из foodItemTypeMap, используя этот подход:

Iterator<Entry<String, String>> iterator = foodItemTypeMap.entrySet().iterator();
while (iterator.hasNext()) {
if (iterator.next().getKey().equals("Carrot"))
iterator.remove();
}

Структурные изменения на карте могут не поддерживаться, если мы не используем собственные методы итератора для обновления. Как видно из приведенного выше фрагмента, мы вызываем метод remove() для объекта итератора, а не для карты. Это обеспечивает потокобезопасную операцию удаления.

Мы можем добиться того же результата в Java 8 или более поздних версиях, используя операцию removeIf :

foodItemTypeMap.entrySet()
.removeIf(entry -> entry.getKey().equals("Grape"));

3.2. Использование ConcurrentHashMap<K, V>

Класс java.util.concurrent.ConcurrentHashMap обеспечивает потокобезопасные операции . Итераторы для ConcurrentHashMap используют только один поток за раз. Следовательно, они обеспечивают детерминированное поведение для параллельных операций.

Мы можем указать количество одновременных операций потока, разрешенных с помощью ConcurrencyLevel .

Давайте используем базовый метод удаления для удаления записей в ConcurrentHashMap :

ConcurrentHashMap<String, String> foodItemTypeConcMap = new ConcurrentHashMap<>();
foodItemTypeConcMap.put("Apple", "Fruit");
foodItemTypeConcMap.put("Carrot", "Vegetable");
foodItemTypeConcMap.put("Potato", "Vegetable");

for (Entry<String, String> item : foodItemTypeConcMap.entrySet()) {
if (item.getKey() != null && item.getKey().equals("Potato")) {
foodItemTypeConcMap.remove(item.getKey());
}
}

4. Вывод

Мы рассмотрели различные сценарии удаления записи в Java HashMap . Если не повторять, мы можем безопасно использовать стандартные методы удаления записей, предоставляемые интерфейсом java.util.Map .

Если мы обновляем карту во время итерации, обязательно используйте методы удаления для инкапсулирующего объекта. Кроме того, мы проанализировали альтернативный класс ConcurrentHashMap , который позволяет выполнять потокобезопасные операции обновления Map .