immutable.Map.map有什么用?

问题描述 投票:1回答:1

immutable.Map.map如何运作?看起来文档有问题:

def map[B](f: (A) ⇒ B): Map[B]

[用例]通过将函数应用于此不可变映射的所有元素来构建新集合。

完整签名

def map[B, That](f: ((A, B)) ⇒ B)(implicit bf: CanBuildFrom[Map[A, B], B, That]): That
  • Map[B]没有意义,因为Map有两个类型参数。
  • 在完整签名中,B的类型参数mapB的类型参数Map之间存在名称冲突。
scala
1个回答
4
投票

可以理解的混淆源于map没有在Map中实现,而是在TraversableLike中实现。但是,子类继承的函数文档。

TraversableLike采用两个类型参数TraversableLike[+A, +Repr],地图函数具有签名TraversableLike.map[B](f: (A) ⇒ B): Traversable[B]。在Map的api文档中,Traversable[B]继承并部分调整了Map[B]的文档,但来自BTraversableLike未解析为(A, B)形式Map

(可能是Scaladoc中的一个错误,可能无法修复,因为可能存在擦除问题。但这只是猜测我。)

如果在成员文档正上方配置成员的可见性,则可以检查Map中实际实现的内容。

编辑:

现在回答你的核心问题:

如果文档会给我们,我们可以直观地阅读

如果我们为了可读性而简化它

如果我们进一步使用更多的自然语言而不是首字母缩略词,Map[A, B]的地图签名可能如下所示:

map[ResultItem, ResultCollection](f: (A,B) => ResultItem)(implicit bf: CanBuildFrom[Map[A, B], ResultItem, ResultCollection]): ResultCollection

因此,基本上你将一个函数应用于Map的每个键值对,它将类型(A,B)的键值对转换为类型为ResultType的值。

由于您可以从地图(或任何其他集合)构建几乎任何类型的集合,因此此结果类型不必是另一个元组。 ResultCollection不一定是另一个Map。例如。:

Map("1" -> 1, "2" -> 2).map((keyValuePair: (String, Int)) => keyValuePair._2)

或短

Map("1" -> 1, "2" -> 2).map(_._2)

List(1, 2)作为结果,List[Int]作为ResultCollection,Int作为ResultItem。

这是可能的,因为隐式CanBuildFrom参数添加了一个隐式构建器,该构建器获取map函数的结果并将其附加到其构建器结果。在大多数情况下,CanBuildFrom是由编译器推断的。但是,有些情况下无法推断出正确的结果集合。

在这种情况下,您必须为编译器提供更多信息:

val test2: Vector[Int] = Map("1" -> 1, "2" -> 2).map(_._2)(collection.breakOut)
val test3: Set[Int] = Map("1" -> 1, "2" -> 2).map(_._2)(collection.breakOut)

有关breakOutCanBuildFrom的更多信息,我建议使用this answer

© www.soinside.com 2019 - 2024. All rights reserved.