简体   繁体   English

Java Guava:在迭代时从Multimap中删除并放回元素

[英]Java Guava: Remove and put back elements from Multimap while iterating

What I'm trying to achieve is the following: While iterating over both the keys and values of a Multimap<K,V> , I want to remove and put back elements from this list. 我想要实现的是:在迭代Multimap<K,V>的键和值时,我想从这个列表中删除并放回元素。 Any approach I've tried ends up in a ConcurrentModificationException. 我尝试过的任何方法最终都会出现在ConcurrentModificationException中。 This remove-and-put-back-approach is required to implement a backtrack search (see here: Implementing a backtrack search with heuristic? ) 这种删除和放回方法是实现回溯搜索所必需的(参见此处: 使用启发式实现回溯搜索?

This may look like: 这可能看起来像:

Multimap<K,V> multimap = HashMultimap.create();
Iterator keyIterator = multimap.keySet().iterator();

while(keyIterator.hasNext()) {
  K key = keyIterator.next();
  Collection values = multimap.get(key);

  Iterator valueIterator = values.iterator();
  while(valueIterator.hasNext()) {
    V myValue = valueIterator.next();
    if(special) {
      valueIterator.remove();
      keyIterator.remove();
      // recursion
      // put back Collection with key but without myValue <-- HOW?
    }
  }
}

One solution is to iterate over a copy of keySet , eg 一种解决方案是迭代keySet的副本,例如

K[] array = multiMap.keySet().toArray(new K[0]);
for(int i = 0; i < array.length; i++) {
    K key = array[i];
    ...
}

Changes to the underlying map won't be reflected in array , so you won't get a ConcurrentModificationException if you use an Iterator on it, and you won't get any weird behavior if you iterate over it with a for loop. 对底层映射的更改不会反映在array ,因此如果对其使用Iterator ,则不会得到ConcurrentModificationException如果使用for循环Iterator它,则不会产生任何奇怪的行为。

Another option is to copy-paste the source code for MultiMap into a new collection MyMultiMap , except that you'd replace the top-level HashMap with a ConcurrentHashMap - the latter's iterators won't throw ConcurrentModificationExceptions . 另一个选择是将MultiMap的源代码复制粘贴到新的集合MyMultiMap ,除了用ConcurrentHashMap替换顶级HashMap - 后者的迭代器不会抛出ConcurrentModificationExceptions

Another option is to coalesce the two loops into one loop, and iterate directly over the map's entries - this way you'll only have one iterator, so you won't have the problem of one iterator causing ConcurrentModificationExceptions in a second iterator. 另一个选择是将两个循环合并为一个循环,并直接遍历map的entries - 这样你只有一个迭代器,所以你不会遇到一个迭代器在第二个迭代器中导致ConcurrentModificationExceptions的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM