概述
一个 HashMap 将Entry存储在具有唯一键的(键,值)对中。 如果您尝试再次添加相同的键,则该特定键的值将被覆盖。
我们可以使用键从 HashMap 中删除条目,因为键在 HashMap 中是唯一的。
通过remove(Object key) 方法删除
官方说明文档:https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/HashMap.html#remove(java.lang.Object)
假设我们有如下的数据
HashMap<String, String> foodItemTypeMap = new HashMap<>();
foodItemTypeMap.put("Apple", "Fruit");
foodItemTypeMap.put("Banana", "Fruit");
foodItemTypeMap.put("Pineapple", "Fruit");
foodItemTypeMap.put("Grape", "Fruit");
foodItemTypeMap.put("Mango", "Fruit");
foodItemTypeMap.put("Carrot", "Vegetable");
foodItemTypeMap.put("Potato", "Vegetable");
foodItemTypeMap.put("Spinach", "Vegetable");
现在需求来了,我们要删除【Pineapple】的数据
public class RemoveEntryHashMap {
public static void main(String[] args) {
HashMap<String, String> foodItemTypeMap = new HashMap<>();
foodItemTypeMap.put("Apple", "Fruit");
foodItemTypeMap.put("Banana", "Fruit");
foodItemTypeMap.put("Pineapple", "Fruit");
foodItemTypeMap.put("Grape", "Fruit");
foodItemTypeMap.put("Mango", "Fruit");
foodItemTypeMap.put("Carrot", "Vegetable");
foodItemTypeMap.put("Potato", "Vegetable");
foodItemTypeMap.put("Spinach", "Vegetable");
System.out.println("HashMap before any entry removal");
System.out.println(foodItemTypeMap);
foodItemTypeMap.remove("Pineapple");
System.out.println("HashMap after entry removal");
System.out.println(foodItemTypeMap);
}
}
输出:
HashMap before any entry removal
{Potato=Vegetable, Apple=Fruit, Carrot=Vegetable, Grape=Fruit, Mango=Fruit, Pineapple=Fruit, Spinach=Vegetable, Banana=Fruit}
HashMap after entry removal
{Potato=Vegetable, Apple=Fruit, Carrot=Vegetable, Grape=Fruit, Mango=Fruit, Spinach=Vegetable, Banana=Fruit}
通过remove(Object key, Object value)方法删除
官方说明:https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html#remove(java.lang.Object,java.lang.Object)
这个 remove(Object key, Object value) 与上面使用的 remove(Object key) 方法非常相似,但主要区别在于它接受 key 和 value 作为参数。
仅当键和值都与 remove 方法中指定的键值匹配时,它才会从 HashMap 中删除条目。
例如,下面提到的代码片段不会在 HashMap 中执行任何更新,因为数据库中不存在具有相似键值的条目。
foodItemTypeMap.remove("Pineapple", "Vegetable");
System.out.println("HashMap after entry removal");
System.out.println(foodItemTypeMap);
输出:
HashMap after entry removal
{Potato=Vegetable, Apple=Fruit, Carrot=Vegetable, Grape=Fruit, Mango=Fruit, Pineapple=Fruit, Spinach=Vegetable, Banana=Fruit}
下面的代码删除了键 Banana 和值 Fruits 的条目,正如我们在 remove 方法中指定的 (Pineapple, Fruit) 作为参数,并且在 HashMap 中存在一个具有相似键值对的条目。
foodItemTypeMap.remove("Pineapple", "Fruit");
System.out.println("HashMap after entry removal");
System.out.println(foodItemTypeMap);
输出:
HashMap after entry removal
{Potato=Vegetable, Apple=Fruit, Carrot=Vegetable, Grape=Fruit, Mango=Fruit, Spinach=Vegetable, Banana=Fruit}
循环中删除
如果您详细了解 HashMap,那么您必须知道 HashMap 是不同步的。 这意味着如果我们尝试同时添加或删除entry可能会遇到 ConcurrentModificationException。
由于这个原因,需要在外部同步删除操作。
解决这个问题的方法是我们可以使用 java.util.Map 接口的 entrySet() 方法。 它将为我们提供 HashMap 中存在的条目集。
由于返回的entry由关联的 Map 支持,因此如果我们对条entry执行任何结构更改,那么也会对 HashMap 进行更新。
请注意,除非我们使用迭代器自己的方法进行更新,否则可能不支持对Map的结构修改。
下面是此示例代码片段。
public class RemoveEntryHashMap {
public static void main(String[] args) {
HashMap<String, String> foodItemTypeMap = new HashMap<>();
foodItemTypeMap.put("Apple", "Fruit");
foodItemTypeMap.put("Banana", "Fruit");
foodItemTypeMap.put("Pineapple", "Fruit");
foodItemTypeMap.put("Grape", "Fruit");
foodItemTypeMap.put("Mango", "Fruit");
foodItemTypeMap.put("Carrot", "Vegetable");
foodItemTypeMap.put("Potato", "Vegetable");
foodItemTypeMap.put("Spinach", "Vegetable");
System.out.println("HashMap before any entry removal");
System.out.println(foodItemTypeMap);
Iterator<Entry<String, String>> iterator = foodItemTypeMap.entrySet().iterator();
while (iterator.hasNext()) {
if (iterator.next().getKey().equals("Pineapple")) {
iterator.remove();
}
}
System.out.println("HashMap after entry removal");
System.out.println(foodItemTypeMap);
}
}
输出:
HashMap before any entry removal
{Potato=Vegetable, Apple=Fruit, Carrot=Vegetable, Grape=Fruit, Mango=Fruit, Pineapple=Fruit, Spinach=Vegetable, Banana=Fruit}
HashMap after entry removal
{Potato=Vegetable, Apple=Fruit, Carrot=Vegetable, Grape=Fruit, Mango=Fruit, Spinach=Vegetable, Banana=Fruit}
如果是Java8以上,那么下面是更简便的写法
System.out.println("HashMap before any entry removal");
System.out.println(foodItemTypeMap);
foodItemTypeMap.entrySet()
.removeIf(entry -> entry.getKey().equals("Pineapple"));
System.out.println("HashMap after entry removal");
System.out.println(foodItemTypeMap);
也可以通过ConcurrentHashMap解决同步的问题
public class RemoveEntryHashMap {
public static void main(String[] args) {
ConcurrentHashMap<String, String> foodItemTypeMap = new ConcurrentHashMap<>();
foodItemTypeMap.put("Apple", "Fruit");
foodItemTypeMap.put("Banana", "Fruit");
foodItemTypeMap.put("Pineapple", "Fruit");
foodItemTypeMap.put("Grape", "Fruit");
foodItemTypeMap.put("Mango", "Fruit");
foodItemTypeMap.put("Carrot", "Vegetable");
foodItemTypeMap.put("Potato", "Vegetable");
foodItemTypeMap.put("Spinach", "Vegetable");
System.out.println("HashMap before any entry removal");
System.out.println(foodItemTypeMap);
for (Entry<String, String> item : foodItemTypeMap.entrySet()) {
if (item.getKey() != null && item.getKey().equals("Potato")) {
foodItemTypeMap.remove(item.getKey());
}
}
System.out.println("HashMap after entry removal");
System.out.println(foodItemTypeMap);
}
}