错误:类型不匹配flatMap

时间:2016-10-13 17:18:09

标签: scala apache-spark

我是新手来编程和scala,我无法理解map和flatMap之间的区别。 我尝试下面的代码,因为我期望两者都工作,但有错误。

scala> val b = List("1","2", "4", "5")
b: List[String] = List(1, 2, 4, 5)

scala> b.map(x => (x,1))
res2: List[(String, Int)] = List((1,1), (2,1), (4,1), (5,1))

scala> b.flatMap(x => (x,1))
<console>:28: error: type mismatch;
 found   : (String, Int)
 required: scala.collection.GenTraversableOnce[?]
              b.flatMap(x => (x,1))

根据我的理解,flatmap将Rdd输入到String / Int Rdd的集合中。 我想在这种情况下两者都应该没有任何错误。请让我知道我在哪里犯了错误。

由于

4 个答案:

答案 0 :(得分:5)

您需要了解签名如何定义这些方法:

def map[U: ClassTag](f: T => U): RDD[U]

mapT类型获取一个函数,然后输入U并返回RDD[U]

另一方面,flatMap

def flatMap[U: ClassTag](f: T => TraversableOnce[U]): RDD[U]

预计将T类型转换为TraversableOnce[U]的函数,这是Tuple2未实现的特征,并返回RDD[U]。通常,当您想要展平集合集合时使用flatMap,即如果您有RDD[List[List[Int]]并且想要生成RDD[List[Int]],则可以使用identity对其进行flatMap 。

答案 1 :(得分:2)

地图操作返回类型为 U ,其中flatMap返回类型为 TraversableOnce [U] (表示集合)

val b = List("1", "2", "4", "5")
val mapRDD = b.map { input => (input, 1) }
mapRDD.foreach(f => println(f._1 + "  " + f._2))

val flatmapRDD = b.flatMap { input => List((input, 1)) }
flatmapRDD.foreach(f => println(f._1 + "  " + f._2))

答案 2 :(得分:2)

map(func)返回通过函数func传递源的每个元素形成的新分布式数据集。

flatMap(func)与map类似,但每个输入项可以映射到0个或更多输出项(因此func应该返回Seq而不是单个项)。

以下示例可能会有所帮助。

        scala> val b = List("1", "2", "4", "5")
        b: List[String] = List(1, 2, 4, 5)

        scala> b.map(x=>Set(x,1))
        res69: List[scala.collection.immutable.Set[Any]] =     
        List(Set(1, 1), Set(2, 1), Set(4, 1), Set(5, 1))

        scala> b.flatMap(x=>Set(x,1))
        res70: List[Any] = List(1, 1, 2, 1, 4, 1, 5, 1)

        scala> b.flatMap(x=>List(x,1))
        res71: List[Any] = List(1, 1, 2, 1, 4, 1, 5, 1)

        scala> b.flatMap(x=>List(x+1))
        res75: scala.collection.immutable.Set[String] = List(11, 21, 41, 51) // concat




        scala> val x = sc.parallelize(List("aa bb cc dd",  "ee ff gg hh"), 2)

        scala> val y = x.map(x => x.split(" ")) // split(" ") returns an array of words
        scala> y.collect
        res0: Array[Array[String]] = Array(Array(aa, bb, cc, dd), Array(ee, ff, gg, hh))

        scala> val y = x.flatMap(x => x.split(" "))
        scala> y.collect
        res1: Array[String] = Array(aa, bb, cc, dd, ee, ff, gg, hh)

答案 3 :(得分:0)

map执行1对1转换,而flatMap将列表列表转换为单个列表:

scala> val b = List(List(1,2,3), List(4,5,6), List(7,8,90))
b: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 90))

scala> b.map(x => (x,1))
res1: List[(List[Int], Int)] = List((List(1, 2, 3),1), (List(4, 5, 6),1), (List(7, 8, 90),1))

scala> b.flatMap(x => x)
res2: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 90)

另外,如果您有None的列表,则flatMap可用于过滤Option值:

scala> val c = List(Some(1), Some(2), None, Some(3), Some(4), None)
c: List[Option[Int]] = List(Some(1), Some(2), None, Some(3), Some(4), None)

scala> c.flatMap(x => x)
res3: List[Int] = List(1, 2, 3, 4)