我已经下面定义的对象。 但我不明白为什么mapValues身体只有在test1的执行。 即。 为什么是输出:
调用TEST1
调用TEST2
制图:一
制图:两
映射:映射(1 - > XX,2 - > XX)
我有两个斯卡拉2.10和2.11相同的结果进行了测试。
object Test {
def test1: Option[String] = {
val map = Map(1 -> "One", 2 -> "Two")
val mapped = map.mapValues { v =>
println("Mapping: " + v)
"Xx"
}
None
}
def test2: Option[String] = {
val map = Map(1 -> "One", 2 -> "Two")
val mapped = map.mapValues { v =>
println("Mapping: " + v)
"Xx"
}
println("Mapped: " + mapped)
None
}
def main(args: Array[String]): Unit = {
println("Calling test1")
test1
println("Calling test2")
test2
}
}
对方的回答解释了这个问题,但作为一个解决方案,如果你想有一个严格的地图,只要使用普通的map
:
val m = Map(1 -> "One", 2 -> "Two")
val mapped = m.map {
case (k,v) => k -> {
println("Mapping: " + v)
"Xx"
}
}
另外,您也可以定义自己的扩展方法做你想要什么:
import scala.collection.GenTraversableLike
import scala.collection.generic.CanBuildFrom
implicit class HasMapVals[T, U, Repr](val self: GenTraversableLike[(T, U), Repr]) extends AnyVal {
def mapVals[R, That](f: U => R)(implicit bf: CanBuildFrom[Repr, (T, R), That]) = {
self.map { case (k,v) => k -> f(v) }
}
}
val m = Map(1 -> "One", 2 -> "Two")
val mapped = m.mapVals { v =>
println("Mapping: " + v)
"Xx"
}
mapValues
实际上返回一个视图 ,故结果懒惰地计算。 从scaladoc为mapValues
:
返回此映射的至f每个键(在此(密钥))映射的映射图。 将得到的地图包装了原始地图而不复制的任何元件。
因此,例如:
val mapped = Map(1 -> "One", 2 -> "Two").mapValues { v =>
println("Mapping: " + v)
"Xx"
}
在它自己的这个声明时将打印什么。 但是,一旦mapped
被访问时,值将被计算,并且该语句将被打印。 (事实上,该值将被重新计算每次访问时间mapped
)
在Test.test1
,没有什么访问mapped
,因此它们的值永远不会计算。
在Test.test2
,你打印出mapped
,从而触发值的计算。