0.Scala函数式编程

我们将来使用Spark/Flink的大量业务代码都会使用到函数式编程。下面这些事开发中常用的函数式编程。注意这些函数都是操作 Scala 集合的,一般会进行两类操作:转换操作(transformation )和行动操作(actions)(有些人喜欢叫他为聚合操作)。第一种操作类型将集合转换为另一个集合,第二种操作类型返回某些类型的值。

  1. 遍历( foreach )
  2. 映射( map )
  3. 映射扁平化( flatmap )
  4. 过滤( filter )
  5. 是否存在( exists )
  6. 排序( sorted 、 sortBy 、 sortWith )
  7. 分组( groupBy )
  8. 聚合计算( reduce )
  9. 折叠( fold )

1.map的使用详解

集合的映射操作是将来在编写Spark/Flink用得最多的操作,是我们必须要掌握的掌握。map方法接收一个函数,将这个函数应用到每一个元素,返回一个新的列表

【1.1语法结构】

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

【1.2语法解释】

尖叫提示:

  • 1.同foreach一样,map传入的参数也是函数,匿名函数
  • 2.map 函数的逻辑是遍历集合中的元素并对每个元素调用函数。你也可以不调用任何函数,保持返回元素本身,但这样 map无法发挥作用,因为你在映射过后得到的是同样的集合。
  • 3.foreach返回值是Unit,而map返回值是集合,简单来说map就是对集合元素进行加工,不影响集合结构。
  • 4.map和foreach,以及后续其他的集合函数一样,都支持类型推定和用下划线_简化函数定义。

【1.3 map使用演示】

//基础演示
val chars = Seq('a', 'b', 'c', 'd') 
chars.map(ch => ch.toUpper) //输出为List(A, B, C, D)
scala> val numbers = Seq(3, 7, 2, 9, 6, 5, 1, 4, 2)
numbers: Seq[Int] = List(3, 7, 2, 9, 6, 5, 1, 4, 2)
scala> numbers.map(x=>x*x)
res4: Seq[Int] = List(9, 49, 4, 81, 36, 25, 1, 16, 4)

//注意这里打印x,最终返回的也是一个集合,只是空集合,空列表,列表结构不变
scala> numbers.map(x=>println(x))  
3
7
2
9
6
5
1
4
2
res5: Seq[Unit] = List((), (), (), (), (), (), (), (), ())

//标准函数,类型推定,下划线替代
scala> a.map((x:Int)=>x+1)
res8: List[Int] = List(2, 3, 4, 5)

scala> val a = List(1,2,3,4)
a: List[Int] = List(1, 2, 3, 4)

scala> a.map(_+1)
res6: List[Int] = List(2, 3, 4, 5)

scala> a.map(x=>x+1)
res7: List[Int] = List(2, 3, 4, 5)

2.flatten的使用详解

     flatten可以把嵌套的结构展开。当有一个集合的集合,然后你想对这些集合的所有元素进行操作时,就会用到 flatten。如果一个集合里存放的是元组,则没法压平,只能压平集合。flatten比较简单,没有参数。用的多是跟他名字很像的flatmap。

  val abcd = List('a', 'b', 'c', 'd')
  val efgj = List('e', 'f', 'g', 'h')
  val ijkl = List('i', 'j', 'k', 'l')
  val mnop = List('m', 'n', 'o', 'p')
  val qrst = List('q', 'r', 's', 't')
  val uvwx = List('u', 'v', 'w', 'x')
  val yz   = List('y', 'z')
  val alphabet = Seq(abcd, efgj, ijkl, mnop, qrst, uvwx, yz)
  println(alphabet.flatten)
  //结果:// ArrayBuffer(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z)


//必须是集合的集合才能flatte,同时里面的集合不能是元组,否则也无法flatten。
scala>  val abc = List((1,2),(3,4))
abc: List[(Int, Int)] = List((1,2), (3,4))

scala> abc.flatten
<console>:13: error: No implicit view available from (Int, Int) => scala.collection.GenTraversableOnce[B].
       abc.flatten
           ^

scala> val abc= List(1,2,3)
abc: List[Int] = List(1, 2, 3)

scala> abc.flatten
<console>:13: error: No implicit view available from Int => scala.collection.GenTraversableOnce[B].
       abc.flatten
           ^

3.flatMap的使用详解

flatMap结合了map和flatten的功能。接收一个可以处理嵌套列表的函数,然后把返回结果连接起来。可以把flatMap,理解为先map,然后再flatten

【3.1语法结构】

def flatMap[B](f: (A) ⇒ GenTraversableOnce[B]): TraversableOnce[B]

flatMap使用流程如下,对List内部成员先进行map,map的结果为一个返回,然后在返回的新List结果上进行flatten扁平化。简单理解就是flatmap可以拆分成map+flatten

 【尖叫提示】

  • 1.因为flatMap有flatten的操作所以flatMap的调用对象必须是集合的集合,要满足flatten的要求
  • 2.flatMap实际操作中就是可以转化成map函数+flatten函数一起操作,只是前者代码更加简洁
//1.使用map+flat
scala>   val fm  = List("hadoop hive spark flink flume", "kudu hbase sqoop storm")
fm: List[String] = List(hadoop hive spark flink flume, kudu hbase sqoop storm)

scala>  fm.map(x => x.split(" "))
res14: List[Array[String]] = List(Array(hadoop, hive, spark, flink, flume), Array(kudu, hbase, sqoop, storm))

scala> res14.flatten
res15: List[String] = List(hadoop, hive, spark, flink, flume, kudu, hbase, sqoop, storm)
scala>  fm.map(x => x.split(" ")).flatten
res18: List[String] = List(hadoop, hive, spark, flink, flume, kudu, hbase, sqoop, storm)

//2.直接使用flatMap
scala> fm.flatMap(x => x.split(" "))
res23: List[String] = List(hadoop, hive, spark, flink, flume, kudu, hbase, sqoop, storm)
scala> fm.flatMap(_.split(" "))
res20: List[String] = List(hadoop, hive, spark, flink, flume, kudu, hbase, sqoop, storm)

 

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐