传送门
Scala入门系列之一--使用命令行往文件输入数据并读取数据
Scala入门系列之二--数组、元组、列表、集合数据类型简述
Scala入门系列之三--类和方法的创建以及命令行执行scala文件
Scala入门系列之四--类成员的可见性(private)以及用value和value_=进行读取和修改
Scala入门系列之五--主构造器和辅助构造器
Scala入门系列之六--伴生对象和伴生类
Scala入门系列之七--scala中的继承
Scala入门系列之八--scala中的特质(trait),也称接口
Scala入门系列之九--模式匹配两大法宝(match语句和case类)
Scala入门系列之十--包
Scala入门系列之十一--函数式编程基础
Scala入门系列之十二--高阶函数
Scala入门系列之十三--针对容器的操作(遍历/映射/过滤/规约操作)
Scala入门系列之十四--使用IDEA编写Scala代码并Maven打包提交集群运行
传送门
一、高阶函数
1)概念简述:
高阶函数:当一个函数包含其它函数作为其参数或者返回结果为一个函数时,该函数被称为高阶函数
//典例:假设需要分别计算从一个整数到另一个整数的“连加和”、“平方和”以及“2的幂次和”
//方案一:不采用高阶函数
def sumInts(a:Int,b:Int):Int={
if(a > b) 0 else a + sumInts(a+1,b)
}
def sumSquares(a:Int,b:Int):Int={
if(a > b) 0 else a*a + sumSquares(a+1,b)
}
//2的幂次和
def powerOfTwo(x:Int):Int = { if(x == 0) 1 else 2 * powerOfTwo(x - 1) }
def sumPowerOfTwo(a:Int,b:Int):Int={
if(a > b) 0 else powerOfTwo(a) + sumPowersOfTwo(a+1,b)
}
//方案二:采用高阶函数
def sum(f:Int=>Int,a:Int,b:Int):Int = {
if(a>b) 0 else f(a) + sum(f,a+1,b)
}
scala> sum(x=>x,1,5) //直接传入一个匿名函数
//且省略了参数x的类型,因为可以由sum的参数类型推断出来
res8: Int = 15
scala> sum(x=>x*x,1,5) //直接传入另一个匿名函数
res9: Int = 55
scala> sum(powerOfTwo,1,5) //传入一个已经定义好的方法
res10: Int = 62
2)练习:
采用高阶函数实现两个数的加减乘除操作,并打印结果
def sum(f:(Int,Int)=>Int,a:Int,b:Int){ f(a,b) }
sum(x,y=>x+y,2,3)
sum(x,y=>x-y,2,3)
sum(x,y=>x*y,2,3)
sum(x,y=>x/y,2,3)
3)提升:
与前面函数式编程基础结合
val list = List(1, 2, 3, 4, 5, 6, 7, 8)
val lists = List(List(1, 2), List(3, 4), List(5, 6), List(7, 8))
// map
// result: List(2, 3, 4, 5, 6, 7, 8, 9)
list.map((x: Int) => x + 1) // 传入一个匿名函数, 接收每个值+1
list.map((x) => x + 1) // 自动类型推导
list.map(x => x + 1) // 只有一个参数可以去掉括号
list.map(_ + 1) // 使用_占位符表示每一个值
// flatMap: flatten + map
lists.flatten // List(1, 2, 3, 4, 5, 6, 7, 8)
lists.map(_.map(_ + 1)) // List(List(2, 3), List(4, 5), List(6, 7), List(8, 9))
lists.flatMap(_.map(_ + 1)) // List(2, 3, 4, 5, 6, 7, 8, 9)
// filter
list.filter(n => n > 5).foreach(println) // 6,7,8
// reduce
list.reduce(_ + _) // 36
list.reduceLeft(_ + _) // 36
list.reduceRight(_ + _) // 36
list.reduce(_ - _) // -34
list.reduceLeft(_ - _) // -34 从左边开始, 左边减右边, 1-2, (1-2)-3, (1-2-3)-4, ...
list.reduceRight(_ - _) // -4 从右边开始, 左边减右边, 7-8, 6-(7-8), 5-(6-7-8), ...
// fold: 同reduce提供一个初始值, foldLeft提供的初始值在最左, foldRight提供的初始值在最右
list.fold(10)(_ + _) // 46
list.foldLeft(10)(_ + _) // 46
list.foldRight(10)(_ + _) // 46
list.fold(10)(_ - _) // -26
list.foldLeft(10)(_ - _) // -26 从左边开始, 左边减右边, 10-1, (10-1)-2, ...
list.foldRight(10)(_ - _) // -6 从右边开始, 左边减右边, 10, ...