大数据开发工程师-第九周 第4章 Scala函数式编程


第九周 第4章 Scala函数式编程

1
2
3
下面我们来学习一下scala中最重要的内容,函数式编程,其实我们学习Scala这门语言就是因为它的这一个特性,咱们在最开始的时候给大家演示了,使用java代码实现函数式编程是很复杂的,而使用scala代码实现函数式编程就很轻松,很简单了。

这块内容我们在后续工作中会经常使用,需要大家重点掌握。

什么是函数式编程

1
2
3
4
Scala是一门既面向对象,又面向过程的语言。
因此在Scala中有非常好的面向对象的特性,可以使用Scala来基于面向对象的思想开发大型复杂的系统和工程;
而且Scala也面向过程,因此Scala中有函数的概念。
在Scala中,函数与类、对象一样,都是一等公民,所以说scala的面向过程其实就重在针对函数的编程了,所以称之为函数式编程

函数赋值给变量

1
2
Scala中的函数是一等公民,可以独立定义,独立存在,而且可以直接将函数作为值赋值给变量
Scala的语法规定,将函数赋值给变量时,必须在函数后面加上空格和下划线
1
2
3
4
5
6
scala> def sayHello(name: String) { println("Hello, " + name) }
sayHello: (name: String)Unit
scala> val sayHelloFunc = sayHello _
sayHelloFunc: String => Unit = <function1>
scala> sayHelloFunc("scala")
Hello, scala

匿名函数

1
2
3
4
5
Scala中的函数也可以不需要命名,这种函数称为匿名函数
匿名函数的语法格式:(参数名: 参数类型) => 函数体
(参数名: 参数类型) :是函数的参数列表

可以将匿名函数直接赋值给某个变量
1
2
3
4
5
scala> val sayHelloFunc = (name: String) => println("Hello, " + name)

scala> val sayHelloFunc = (name: String) => {println("Hello, " + name)}

注意:如果函数体有多行代码,则需要添加{}

高阶函数

1
2
3
4
5
由于函数是一等公民,所以说我们可以直接将某个函数作为参数传入其它函数
这个功能是极其强大的,也是Java这种面向对象的编程语言所不具备的

这个功能在实际工作中是经常需要用到的
接收其它函数作为当前函数的参数,当前这个函数也被称作高阶函数 (higher-order function)
1
2
3
4
5
6
7
看一个例子:
先定义一个匿名函数,赋值给变量sayHelloFunc
val sayHelloFunc = (name: String) => println("Hello, " + name)

再定义一个高阶函数,这个高阶函数的参数会接收一个函数
参数: (String) => Unit 表示这个函数接收一个字符串,没有返回值
def greeting(func: (String) => Unit, name: String) { func(name) }
1
2
scala> greeting(sayHelloFunc, "scala")
Hello, scala
1
2
3
或者还可以这样用,直接把匿名函数的定义传过来也是可以
scala> greeting((name: String) => println("Hello, " + name),"scala")
Hello, scala
1
2
3
4
5
6
7
8
9
10
高阶函数可以自动推断出它里面函数的参数类型,对于只有一个参数的函数,还可以省去小括号
# 先定义一个高阶函数
def greeting(func: (String) => Unit, name: String) { func(name) }
# 使用高阶函数:完整写法
greeting((name: String) => println("Hello, " + name), "scala")

# 使用高阶函数:高阶函数可以自动推断出参数类型,而不需要写明类型
greeting((name) => println("Hello, " + name), "scala")
# 使用高阶函数:对于只有一个参数的函数,还可以省去其小括号
greeting(name => println("Hello, " + name), "scala")

常用高阶函数

1
2
刚才是我们自己实现的高阶函数,其实我们在工作中自己定义高阶函数的场景不多,大部分场景都是去使用已有的高阶函数
下面我们来看几个常见的高阶函数
1
2
3
4
5
map:对传入的每个元素都进行处理,返回一个元素
flatMap:对传入的每个元素都进行处理,返回一个或者多个元素
foreach:对传入的每个元素都进行处理,但是没有返回值
filter:对传入的每个元素都进行条件判断,如果返回true,则保留该元素,否则过滤掉该元素
reduceLeft:从左侧元素开始,进行reduce操作

map

1
2
3
4
5
6
scala> Array(1, 2, 3, 4, 5).map(num=>{num * 2})
res38: Array[Int] = Array(2, 4, 6, 8, 10)

可以简写为
scala> Array(1, 2, 3, 4, 5).map(_ * 2)
res40: Array[Int] = Array(2, 4, 6, 8, 10)

flatMap

1
2
3
4
5
6
scala> Array("hello you","hello me").flatMap(line=>line.split(" "))
res53: Array[String] = Array(hello, you, hello, me)

可以简写为
scala> Array("hello you","hello me").flatMap(_.split(" "))
res54: Array[String] = Array(hello, you, hello, me)

foreach

1
2
3
4
5
6
7
8
9
10
11
scala> Array(1, 2, 3, 4, 5).map(_ * 2).foreach(num=>println(num))
2 4 6 8
10

scala> Array(1, 2, 3, 4, 5).map(_ * 2).foreach(println(_))
2 4 6 8
10

scala> Array(1, 2, 3, 4, 5).map(_ * 2).foreach(println _)
2 4 6 8
10

filter

1
2
3
4
5
scala> Array(1, 2, 3, 4, 5).filter(num=>num % 2 == 0)
res46: Array[Int] = Array(2, 4)

scala> Array(1, 2, 3, 4, 5).filter(_ % 2 == 0)
res47: Array[Int] = Array(2, 4)

reduceLeft

1
2
3
4
5
6
7
8
9
10
reduceLeft的使用
表示先对元素1和元素2进行处理,然后将结果与元素3处理,再将结果与元素4处理,依次类推spark中有一个reduce函数,和这个函数的效果一致

scala> Array(1, 2, 3, 4, 5).reduceLeft((t1,t2)=>t1+t2)
res50: Int = 15

scala> Array(1, 2, 3, 4, 5).reduceLeft( _ + _)
res49: Int = 15

注意:这里的两个_代表是两个元素

案例:函数式编程

1
2
3
4
统计多个文本内的单词总数
使用scala的io包读取文本文件内的数据

使用List的伴生对象,将多个文件内的内容创建为一个List
1
2
3
4
5
6
7
8
9
10
11
12
13
val lines01 = scala.io.Source.fromFile("D://a.txt").mkString
val lines02 = scala.io.Source.fromFile("D://b.txt").mkString

val lines = List(lines01, lines02)

注意:下面这一行是核心代码,使用了链式调用的函数式编程
lines.flatMap(_.split( " ")).map((_, 1)).map(_._2).reduceLeft(_ + _)


lines.flatMap(_.split( " ")) :表示对每一行数据使用空格进行切割,返回每一个单词
.map((_, 1)) :针对每一个单词,都转成tuple类型,tuple中的第1个元素是这个单词,第2个元素表示单词出现的次数1
.map(_._2) :迭代每一个tuple,获取tuple中的第2个元素
.reduceLeft(_ + _) :对前面获取到的元素进行累加求和

image-20230323112822895

image-20230323113024119

本文标题:大数据开发工程师-第九周 第4章 Scala函数式编程

文章作者:TTYONG

发布时间:2022年03月01日 - 09:03

最后更新:2023年03月23日 - 11:03

原始链接:http://tianyong.fun/%E5%A4%A7%E6%95%B0%E6%8D%AE%E5%BC%80%E5%8F%91%E5%B7%A5%E7%A8%8B%E5%B8%88-%E7%AC%AC%E4%B9%9D%E5%91%A8-%E7%AC%AC4%E7%AB%A0-Scala%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BC%96%E7%A8%8B.html

许可协议: 转载请保留原文链接及作者。

多少都是爱
0%