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
.