Java Guava:迭代和删除 Multimap 的键

Java Guava: Iterating and removing keys of Multimap

我正在尝试迭代 Multimap 并根据任意检查删除一些键及其值。

Multimap<Integer, Character> myMultimap = ArrayListMultimap.create();

myMultimap.keySet().stream().forEach((bin) -> {
    if (random.nextDouble() < p) {
        myMultimap.removeAll(bin);
    }
});

这显然会引发 ConcurrentModificationException。

所以我尝试了:

Iterator<Integer> i = myMultimap.keySet().iterator();
while (i.hasNext()) {
    if (random.nextDouble() < p) {
        i.remove();         
    }
}

然而,这会导致 java.lang.IllegalStateException:自上次调用 remove() 以来,没有调用 next()。 我试过像下面的代码一样玩弄它,但在几次迭代后我仍然遇到同样的错误。

Iterator<Integer> i = myMultimap.keySet().iterator();
while (i.hasNext()) {
    if (random.nextDouble() < p) {
        i.remove();
        i.next();
    } else {
        i.next();
    }
}

您可以遍历地图并将要删除的所有键保存在列表中。

Iterator<Integer> i = myMultimap.keySet().iterator();
List<Integer> keyList = new ArrayList<Integer>();
while (i.hasNext()) {
    if (random.nextDouble() < p)
        keyList.add(i);
}

然后从映射中删除列表的每个条目:

for (Integer key : keyList)
    myMultimap.remove(key);

创建迭代器时,它指向第一个元素之前。您必须先调用 next() 才能调用 remove() 来推进迭代器(即使您不需要该元素)。 remove() 将影响调用 next().

返回的元素

正如Michael Koch 所说,next() 需要在remove() 之前调用。以下代码应该可以工作。

Iterator<Integer> i = myMultimap.keySet().iterator();
while (i.hasNext()) {
    i.next();
    if (random.nextDouble() < p) { 
        i.remove();
    } 
}