📜  在迭代时使用 HashMap 中的值删除条目(1)

📅  最后修改于: 2023-12-03 15:23:38.060000             🧑  作者: Mango

在迭代时使用 HashMap 中的值删除条目

在 Java 中,如果我们需要从一个 HashMap 中删除一些键值对,我们需要使用 Iterator 迭代器来删除条目。使用迭代器,我们可以安全地迭代一个集合并进行删除操作,而不会影响其它正在进行的迭代操作。

问题描述

然而,当我们需要删除 HashMap 中的一些值时,我们就面临一个问题。使用迭代器删除键值对是可以的,但是如果我们仅仅要删除值,则会有一些问题。考虑以下代码:

Map<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
map.put(4, "four");

for (String value : map.values()) {
    if (value.equals("two") || value.equals("three")) {
        map.values().remove(value);
    }
}

System.out.println(map);

输出结果应该是:

{1=one, 4=four}

然而,我们却得到了一个 ConcurrentModificationException 异常!

解决方案

原因是在遍历 HashMap 中的值时删除了值,而且是通过 HashMapvalues() 方法来遍历的。在遍历过程中改变了 HashMap 的大小,而不是通过迭代器进行删除。因此,遍历过程就不再有效了。

我们可以通过遍历 HashMap 的键值对来解决这个问题。以下是一种解决方案:

Map<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
map.put(4, "four");

Iterator<Map.Entry<Integer, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
    Map.Entry<Integer, String> entry = iterator.next();

    if (entry.getValue().equals("two") || entry.getValue().equals("three")) {
        iterator.remove();
    }
}

System.out.println(map);

输出结果应该是:

{1=one, 4=four}

现在我们成功地从 HashMap 中删除了键值为 "two""three" 的条目,而不会抛出异常了!

总结

在迭代 HashMap 的值时,应该使用键值对遍历,并且使用迭代器进行删除操作。如果需要删除值而非键值对,应该使用键值对遍历并使用迭代器删除操作。这样设计是为了防止在并发修改 HashMap 的大小时,修改操作导致迭代器失效。