我是新手来编程和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的集合中。 我想在这种情况下两者都应该没有任何错误。请让我知道我在哪里犯了错误。
由于
答案 0 :(得分:5)
您需要了解签名如何定义这些方法:
def map[U: ClassTag](f: T => U): RDD[U]
map
从T
类型获取一个函数,然后输入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)