了解List中的flatMap声明

时间:2016-08-29 10:46:07

标签: scala collections implicit

我刚看了List.flatMap声明,对此感到有些惊讶。

final override def flatMap[B, That](f: A => GenTraversableOnce[B])
                 (implicit bf: CanBuildFrom[List[A], B, That]): That

object List定义的地方:

implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, List[A]] =
    ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]

因此,如果我们在flatMap上调用List,我们将获得List,如果它始终存在That类型,我就不会看到任何一点被推断为List[B](因为implicit)。

2 个答案:

答案 0 :(得分:5)

  

因此,如果我们在flatMap上调用List[A],我们将获得List[A]而我不会   如果That类型总是被推断为List[B]

,请参阅flatMap类型中的任何一点

您遗失的一件事是List[+A]实际上并未定义TraversableLike。它继承自CanBuildFrom,这是大多数Scalas集合使用的特征。它们中的每一个都可以提供隐式CanBuildFrom,它可以被覆盖以提供不同的结果集合。

如果您想了解使用自定义scala> :pa // Entering paste mode (ctrl-D to finish) import scala.collection.generic.CanBuildFrom import scala.collection.immutable._ import scala.collection.mutable import scala.{List, Vector} implicit val listToVectorCBF = new CanBuildFrom[List[Int], Int, Vector[Int]] { override def apply(from: List[Int]): mutable.Builder[Int, Vector[Int]] = this.apply() override def apply(): mutable.Builder[Int, Vector[Int]] = Vector.newBuilder } // Exiting paste mode, now interpreting. scala> List(1,2,3).flatMap(List(_)) res6: Vector[Int] = Vector(1, 2, 3)

可以执行的操作
{{1}}

答案 1 :(得分:2)

嗯...... implicit CanBuildFrom可以用来直接构建不同类型的结构而不是List,从而节省了一个额外的步骤。让我们看看下面的例子,

val list = List(List(1, 2, 3), List(4, 5, 6))

// now if we do a flatmap withtout overriding the implicit CanBuildFrom
val newList = list.flatMap(l => l.map(i => (i,i)))

// new list will be a List[(Int, Int)]
// but what if you wanted a map

val newMap = newList.toMap

// But you actually needed to traverse the list twice in this case

// But we can avoid the second traversal if we chose to override the implicit
val newMap2 = list.flatMap(l => l.map(i => (i,i)))(collection.breakout)