当我在 Map
上使用 filterKeys
或 mapValues
来创建新的 Map
时,我的函数每次我使用新的 Map
时,传入这些方法的代码似乎都会被执行。难道它们不应该只执行一次来生成新的Map
吗?
在此示例中,了解 println
如何多次发生。
// printlns happen when creating the map
scala> val myMap = Map(1 -> 1, 2 -> 2, 3 -> 3).filterKeys { i =>
println(s"filterKeys$i")
i < 5
}.mapValues { i =>
println(s"mapValues$i")
i + 1
}
filterKeys1
mapValues1
filterKeys2
mapValues2
filterKeys3
mapValues3
myMap: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 2 -> 3, 3 -> 4)
// printlns happen again!
scala> myMap.toString()
filterKeys1
mapValues1
filterKeys2
mapValues2
filterKeys3
mapValues3
res29: String = Map(1 -> 2, 2 -> 3, 3 -> 4)
// and again!
scala> myMap + (4 -> 5)
filterKeys1
mapValues1
filterKeys2
mapValues2
filterKeys3
mapValues3
res30: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5)
我希望行为与 .map()
相同。传递给 map 的函数,仅对每个项目运行一次,并且在将来使用结果 map 时不会再次运行:
// printlns happen when creating the map
scala> val myMap = Map(1 -> 1, 2 -> 2, 3 -> 3).map { i =>
println(s"map$i")
i
}
map(1,1)
map(2,2)
map(3,3)
myMap: scala.collection.immutable.Map[Int,Int] = Map(1 -> 1, 2 -> 2, 3 -> 3)
// printlns not run again :)
scala> myMap.toString
res32: String = Map(1 -> 1, 2 -> 2, 3 -> 3)
最佳答案
scaladocs for mapValues
和 filterKeys
两者都提到它们返回一个结果映射,该映射包装原始映射而不复制任何元素。源码中可以看到mapValues
返回 MappedValues
的实例它会为每次重复的 foreach
、iterator
和 get
调用重新运行您的函数。
因为这个行为与.map()
不一致,所以有ticket SI-4776 open 来重命名方法或更改其返回类型以使这一点更加明显,但是票证已经开放很长时间了,因此不要指望这种行为很快就会改变。
更新:自 Scala 2.13 起,这些方法已被弃用,并计划在未来版本中修复:
(Since version 2.13.0) Use .view.mapValues(f). A future version will include a strict version of this method (for now, .view.mapValues(f).toMap).
除了建议的 view.mapValues(f).toMap
之外,您还可以使用 transform
而不是 mapValues
来解决此问题和 filter
而不是 filterKeys
:
val myMap = Map(1 -> 1, 2 -> 2, 3 -> 3).filter { case (i, _) =>
println(s"filterKeys$i")
i < 5
}.transform { (_, i) =>
println(s"mapValues$i")
i + 1
}
// no printlns when the Map is used again!
myMap.toString
关于scala - `filterKeys` 和 `mapValues` 被执行多次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43173795/