1. 概述
在这篇文章中,我们将讨论从Java HashMap 中移除条目的不同方法。
2. 引言
HashMap 使用唯一的键存储*(Key, Value)*对。一个想法是使用键作为标识符来从映射中移除关联的条目。
我们可以利用java.util.Map
接口提供的方法,通过键作为输入来进行条目移除。
2.1. 使用方法remove(Object key)
让我们通过一个简单的例子来尝试。我们有一个将食物项目与食物类型关联的映射:
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. 使用方法remove(Object key, Object value)
这是第一个方法的变体,接受键和值作为输入。在我们想要仅当键映射到特定值时删除条目的情况下,我们会使用这个方法。
在foodItemTypeMap
中,“Grape”键并未映射到“Vegetable”值。
因此,下面的操作不会导致任何更新:
foodItemTypeMap.remove("Grape", "Vegetable");
// Current Map Status: {Potato=Vegetable, Carrot=Vegetable, Grape=Fruit, Mango=Fruit, Spinach=Vegetable}
现在,让我们探讨在HashMap中进行其他条目移除场景。
3. 在迭代过程中移除条目
HashMap
类是非同步的。如果尝试并发地添加或删除条目,可能会导致ConcurrentModificationException
。因此,我们需要在外部同步移除操作。
3.1. 在外部对象上同步
一种方法是在封装HashMap
的对象上同步。例如,我们可以使用java.util.Map
接口的entrySet()
方法获取HashMap
中的条目集合。返回的集合由关联的Map
支持。
因此,集合的任何结构修改都会导致Map
的更新。
让我们使用这种方法从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
中使用基本的remove
方法移除条目:
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
接口提供的标准移除方法。
在迭代过程中更新Map
时,必须在封装对象上使用remove
方法。此外,我们还分析了一个替代类ConcurrentHashMap
,它提供了对Map
进行线程安全更新操作的能力。