前言
day06,我们学习了scala类的继承、抽象类、trait、包及包对象。今天学习scala的函数式编程及常用高阶函数。
scala函数的基本介绍
在scala中,函数是“头等公民”,可以像定义一个变量的方式来定义,可以在变量中存放函数,即:将函数作为变量的值(值函数)。
scala中的函数的定义语法如下:
def 函数的名字(参数列表) : 返回值 = {函数体}
匿名函数与高阶函数
没有名字的函数就是匿名函数。如下在scala命令行下的操作,就是定义了一个匿名函数。
scala> (x:Int) => x*3
res0: Int => Int = <function1>
scala>
函数的参数是函数,或者函数的实现是函数,就属于高阶函数。
匿名函数不能直接使用,它是为了给高阶函数传参用的。
scala> var array = Array(1,2,3,4)
array: Array[Int] = Array(1, 2, 3, 4)
#如下map中的参数就是传入了一个匿名函数
scala> array.map((x:Int) => x*3)
res1: Array[Int] = Array(3, 6, 9, 12)
scala>
如下在scala命令行中进行一些演示,定义一个高阶函数,对数字进行一些运算。
#如下就是创建了一个高阶函数sumfun,它的参数是一个匿名函数 (Double) => Double
scala> def sumfun(func:(Double) => Double) = func(10)
sumfun: (func: Double => Double)Double
cala> import scala.math._
import scala.math._
#如下就是对10进行了sin运算
scala> sumfun(sin)
res8: Double = -0.5440211108893698
scala>
#如下求10的开根号
scala> sumfun(sqrt)
res10: Double = 3.1622776601683795
scala>
常用高阶函数介绍
在实际中,我们经常使用的是scala提供的高阶函数,如下是一些常用的高阶函数的介绍。
map
相当于循环,对集合中的每个元素调用map中的匿名函数进行处理,不改变原来的集合,返回一个新的集合。
如下在scala命令行中进行一些演示:
scala> var array = Array(1,2,3,4)
array: Array[Int] = Array(1, 2, 3, 4)
#使用map对array的每个元素乘2
scala> var b = array.map(_*2)
b: Array[Int] = Array(2, 4, 6, 8)
#得到的是一个新的集合
scala> b.foreach(println)
2
4
6
8
scala>
foreach
相当于一个循环,对集合中的每个元素进行操作(接收一个函数),与map的区别在于,foreach不返回结果。foreach一般用于遍历集合,然后打印。
如下在scala命令行中进行一些演示:
scala> var array = Array(1,2,3,4)
array: Array[Int] = Array(1, 2, 3, 4)
scala> array.foreach(println)
1
2
3
4
scala>
filter
选择满足条件的数据,不改变原来的集合,返回的是一个新的集合。
如下在scala命令行中进行一些演示:
scala> var array = Array(1,2,3,4)
array: Array[Int] = Array(1, 2, 3, 4)
#过滤出来偶数的元素,返回的是一个新的集合
scala> var c = array.filter(_%2==0)
c: Array[Int] = Array(2, 4)
scala> c.foreach(println)
2
4
scala>
zip
把多个集合合并成一个集合,返回的是一个新的集合,新集合中的元素是元组。
scala> var a = List(2,3,4)
a: List[Int] = List(2, 3, 4)
#zip返回的是一个新的集合,新集合中的元素是元组Tuple
scala> a.zip(List(100,200,399))
res19: List[(Int, Int)] = List((2,100), (3,200), (4,399))
#如果合并的两个集合长度不一样,则长度大的集合中的多出的元素会被丢掉
scala> a.zip(List(100,200,399,488))
res20: List[(Int, Int)] = List((2,100), (3,200), (4,399))
scala>
partition
根据断言(条件,通过匿名函数实现的),进行分区。
像如下的把奇数放在一个分区,偶数放在一个分区。其实这个分区分出来后,是把不同区的数据放到不同的集合中。
scala> var c = List(1,2,3,4,5,6,7,8,9)
c: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
#把奇数放在一个区,把偶数放在一个区
scala> c.partition((i:Int) => i%2 == 0)
res24: (List[Int], List[Int]) = (List(2, 4, 6, 8),List(1, 3, 5, 7, 9))
#简写
scala> c.partition(_%2 == 0)
res25: (List[Int], List[Int]) = (List(2, 4, 6, 8),List(1, 3, 5, 7, 9))
scala>
find
查找,查找出第一个满足条件的元素,即使集合中存在多个满足条件的元素,也是只查找第一个满足条件的元素。
scala> var d = List(1,2,3,4,5,6,7,8,9)
d: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
#返回的是第一个满足条件的元素
scala> d.find(_%3 == 0)
res26: Option[Int] = Some(3)
#如果没有满足条件的元素,则返回None
scala> d.find(_%3 == 10)
res27: Option[Int] = None
scala>
flatten
将嵌套的集合(外面是一个集合,集合中的元素又是集合)展开成一个集合。
scala> var e = List(List(1,2,3),List(4,5,6),List(7,8,9))
e: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9))
#flatten函数是没有参数的,不用写()
scala> e.flatten
res28: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
scala>
flatMap
相当于flatten和map合并,是先运行map,再运行flatten。flatMap一般是在spark对数据的切分,切分后完成后展开成每一个元素。
scala> var f = Array("Hello word linux","CentOS ubuntu")
f: Array[String] = Array(Hello word linux, CentOS ubuntu)
scala> f.flatMap(_.split(" "))
res36: Array[String] = Array(Hello, word, linux, CentOS, ubuntu)
#上面 f.flatMap(_.split(" "))的运行过程是这样的
scala> var f = Array("Hello word linux","CentOS ubuntu")
#先运行map
scala> var g = f.map(_.split(" "))
g: Array[Array[String]] = Array(Array(Hello, word, linux), Array(CentOS, ubuntu))
#再运行flatten
scala> g.flatten
res39: Array[String] = Array(Hello, word, linux, CentOS, ubuntu)