bigdata-32-函数式编程体验

简介: bigdata-32-函数式编程体验

什么是函数式编程

Scala是一门既面向对象,又面向过程的语言。

因此在Scala中有非常好的面向对象的特性,可以使用Scala来基于面向对象的思想开发大型复杂的系统和工程;

而且Scala也面向过程,因此Scala中有函数的概念。

在Scala中,函数与类、对象一样,都是一等公民,所以说scala的面向过程其实就重在针对函数的编程了,所以称之为函数式编程

函数赋值给变量

Scala中的函数是一等公民,可以独立定义,独立存在,而且可以直接将函数作为值赋值给变量

Scala的语法规定,将函数赋值给变量时,必须在函数后面加上空格和下划线

来看一个案例:将函数赋值给变量

scala> def sayHello(name: String) { println("Hello, " + name) }

sayHello: (name: String)Unit

scala> val sayHelloFunc = sayHello _

sayHelloFunc: String => Unit =

scala> sayHelloFunc("scala")

Hello, scala

匿名函数

Scala中的函数也可以不需要命名,这种函数称为匿名函数

匿名函数的语法格式:(参数名: 参数类型) => 函数体

(参数名: 参数类型) :是函数的参数列表

可以将匿名函数直接赋值给某个变量

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

sayHelloFunc: String => Unit =

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

sayHelloFunc: String => Unit =

高阶函数

由于函数是一等公民,所以说我们可以直接将某个函数作为参数传入其它函数

这个功能是极其强大的,也是Java这种面向对象的编程语言所不具备的

这个功能在实际工作中是经常需要用到的

  1. 接收其它函数作为当前函数的参数,当前这个函数也被称作高阶函数 (higher-order function)

看一个例子:

先定义一个匿名函数,赋值给变量sayHelloFunc

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

再定义一个高阶函数,这个高阶函数的参数会接收一个函数

参数: (String) => Unit 表示这个函数接收一个字符串,没有返回值

def greeting(func: (String) => Unit, name: String) { func(name) }

  1. 1

使用:

scala> greeting(sayHelloFunc, "scala")

Hello, scala

或者还可以这样用,直接把匿名函数的定义传过来也是可以

scala> greeting((name: String) => println("Hello, " + name),"scala")

Hello, scala

  1. 高阶函数可以自动推断出它里面函数的参数类型,对于只有一个参数的函数,还可以省去小括号

# 先定义一个高阶函数

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. map:对传入的每个元素都进行处理,返回一个元素
  2. flatMap:对传入的每个元素都进行处理,返回一个或者多个元素
  3. foreach:对传入的每个元素都进行处理,但是没有返回值
  4. filter:对传入的每个元素都进行条件判断,如果返回true,则保留该元素,否则过滤掉该元素
  5. reduceLeft:从左侧元素开始,进行reduce操作

map

map的使用:

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

flagMap的使用

scala> Array("hello you","hello me").flatMap(line=>line.split(" "))

res53: Array[String] = Array(hello, you, hello, me)

foreach

foreach的使用

scala> Array(1, 2, 3, 4, 5).map(_ * 2).foreach(num=>println(num))

2

4

6

8

10

filter

filter的使用

scala> Array(1, 2, 3, 4, 5).filter(num=>num % 2 == 0)

res46: Array[Int] = Array(2, 4)

reduceLeft

reduceLeft的使用

表示先对元素1和元素2进行处理,然后将结果与元素3处理,再将结果与元素4处理,依次类推

spark中有一个reduce函数,和这个函数的效果一致

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

res50: Int = 15

这个操作操作就相当于1 + 2 + 3 + 4 + 5

案例:函数式编程

统计多个文本内的单词总数

使用scala的io包读取文本文件内的数据

val lines01 = scala.io.Source.fromFile("D://a.txt").mkString

val lines02 = scala.io.Source.fromFile("D://b.txt").mkString

使用List的伴生对象,将多个文件内的内容创建为一个List

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( + ):对前面获取到的元素进行累加求和

目录
打赏
0
0
0
0
333
分享
相关文章
大数据开发基础的编程语言的Scala的Actor编程
当谈到大数据开发时,Scala是一个非常流行的编程语言。Scala是一种静态类型的编程语言,它结合了面向对象和函数式编程范型。Scala为大数据处理提供了强大的支持,因此在许多大数据项目中被广泛使用。其中,Scala的Actor编程模型可以帮助我们设计和实现高效的并发系统。
108 0
大数据开发基础的编程语言的Scala的函数式编程范式
Scala是一种支持函数式编程范式的编程语言,它允许开发者使用函数和不可变数据结构来实现程序逻辑。本文将介绍Scala中函数式编程范式的概念和用法,帮助开发者更好地理解和应用这门语言。
118 0
Scala快速入门-8-特质
Scala和Java一样不允许类继承多个超类,特质解决这一局限性 类可以实现任意数量的特质 当将多个特质叠加在一起时,顺序很重要,其方法先被执行的特质排在更后面 Scala特质可以提供方法和字段的实现 特质要求实现它们的类具备特定的字段、方法或超类 特质可以同时拥有抽象方法和具体方法,而类可以实现多个特质