迭代时从地图中删除键/值

div*_*ges 6 groovy map

我正在创建这样的地图:

def myMap = [:]
Run Code Online (Sandbox Code Playgroud)

映射基本上是键的对象和值的int.当我遍历地图时,我会减少该值,如果它为0,我将其删除.我已经尝试了myMap.remove(),但我得到了ConcurrentModificationError- 这是公平的.所以我继续使用it.remove(),这给了我奇怪的结果.

基本上,我的代码是这样的:

myMap.each {
    it.value--;

    if( it.value <= 0 )
        it.remove();
}
Run Code Online (Sandbox Code Playgroud)

很简单.我的问题是,如果我myMap.size()在删除之前和之后打印,它们都是一样的.如果我打电话myMap.containsKey( key ),它给了我true,关键还在那里.

但是,如果我打印出这样的地图:

myMap.each { System.out.println( "$it.key: $it.value" ); }
Run Code Online (Sandbox Code Playgroud)

我什么都没得到,并且打电话myMap.keySet()然后myMap.values()回来.

有谁知道发生了什么?

Dón*_*nal 11

这应该比Tim的答案更有效(因为你只需要迭代一次地图).不幸的是,它也非常冗长

def map = [2:1, 3:4]
def iterator = map.entrySet().iterator()

while (iterator.hasNext()) {

  if (iterator.next().value - 1 <= 0) {
    iterator.remove()
  }
}

// test that it worked
assert map == [3:4]
Run Code Online (Sandbox Code Playgroud)


tim*_*tes 6

你能做这样的事吗:

myMap = myMap.each { it.value-- }.findAll { it.value > 0 }
Run Code Online (Sandbox Code Playgroud)

这将从每个值中减去一个,然后返回一个仅包含值大于零的条目的新映射.

你不应该remove在Map上调用该方法Entry,它应该是Map内部使用的私有方法(参见第7行的Java 7实现),所以你自己调用它会让封闭的Map变成各种各样的麻烦(它不知道它正在丢失条目)

Groovy允许您调用私有方法,因此您可以在Java类的后面执行此类操作

编辑 - 迭代器方法

另一种方式是:

myMap.iterator().with { iterator ->
  iterator.each { entry ->
    entry.value--
    if( entry.value <= 0 ) iterator.remove()
  }
}
Run Code Online (Sandbox Code Playgroud)