【大纲】
【正文】
1.【结论】概念
函数式编程,是指方法的参数列表可以接收函数对象。如,getSum(10,20)就不是函数式编程,getSum(函数对象)就是函数式编程
2.【结论】特点
0.用_简化函数定义
在函数式编程中,作为方法参数的函数对象如果是个匿名函数,则当函数参数只在函数体中出现一次,且没用嵌套,就可以使用下划线来简化函数定义,能省略参数的参数
如:
对象.foreach(x => println(x))
可简化为:
对象.foreach(println(_))
val a = 对象.reduce((x, y) => x + y)
可简化为:
val a = 对象.reduce(_ + _)
3.函数式编程的常用方法
3.1.foreach遍历(并发)
3.1.1.【结论】作用
遍历数组、集合与其他可迭代对象,对每个元素进行处理后,不返回值
3.1.2.方法本法
def foreach(f:A => Unit):Unit
# 说明:
0.方法的参数
f:A => Unit,代表接收一个函数对象,函数的参数是可迭代对象的类型A,函数返回值是Unit
1.方法的返回值
Unit
3.1.3.【结论】使用示例
object Foreach {
def main(args: Array[String]): Unit = {
val aw = Array(1,2,3,4,5)
aw.foreach(x => println(x)) // 效果:1 2 3 4 5
// 用_简化函数定义
aw.foreach(println(_)) // 效果:1 2 3 4 5
// 遍历后,做点复杂操作
aw.foreach(x => {
println(x + 1)
println(x)
})
}
}
3.2.map映射(并发)
3.2.1.【结论】作用
遍历数组、集合与其他可迭代对象,对每个元素进行处理后,装入新对象进行返回,返回值类型 = 原可迭代对象
3.2.2.方法本法
def map[B](f:A => B):TraversableOnce[B]
# 说明:
0.方法的泛型
[B],最终返回的集合的泛型是B,可省略不写
1.方法的参数
f:A => B,代表接收一个函数对象,函数的参数是可迭代对象的类型A,函数返回值类型是B
2.方法的返回值
TraversableOnce[B],方法的返回值是B类型的集合,可省略不写
3.2.3.【结论】使用示例
object MapFunction {
def main(args: Array[String]): Unit = {
val a = Array(1,2,3)
val b = a.map(x => x + 1)
println(b) // 效果:[I@d041cf
b.foreach(println(_)) // 效果:2 3 4
}
}
3.3.flatMap扁平化映射
3.3.1.【结论】作用
先map再flatten
3.3.2.方法本法
def flatMap[B](f:A => GenTraversableOnce[B]): TraversableOnce[B]
# 说明:
0.方法的泛型
[B],最终要返回的集合元素类型,可省略不写
1.方法的参数
f:A => GenTraversableOnce[B],代表接收一个函数对象,函数的参数是可迭代对象的类型A,函数返回值类型是一个集合B
2.方法的返回值
TraversableOnce[B],方法的返回值是B类型的集合,可省略不写
3.3.3.【结论】使用示例
# 需求
有一个包含了若干个文本行的列表:"hadoop hive spark flink flume", "kudu hbase sqoop storm"
获取到文本行中的每一个单词,并将每一个单词都放到列表中
# 实现
object FlatMap {
def main(args: Array[String]): Unit = {
val a = List("hadoop hive spark flink flume", "kudu hbase sqoop storm")
val b = a.flatMap(x => x.split(" "))
println(b) // 效果:List(hadoop, hive, spark, flink, flume, kudu, hbase, sqoop, storm)
}
}
3.4.filter过滤出
3.4.1.【结论】作用
遍历数组、集合与其他可迭代对象,对每个元素进行条件判断后,结果是true的元素装入新对象进行返回,返回值类型 = 原可迭代对象
3.4.2.方法本法
def filter(f:A => Boolean): TraversableOnce[A]
# 说明:
0.方法的参数
f:A => Boolean,代表接收一个函数对象,函数的参数是可迭代对象的类型A,函数返回值类型是Boolean
1.方法的返回值
TraversableOnce[A],方法的返回值是A类型的集合,可省略不写
# 注意:
0.filterNot方法类似,只不过是元素判断的结果为false才返回
3.4.3.【结论】使用示例
# 需求:
过滤出所有的偶数
# 实现:
object Filter {
def main(args: Array[String]): Unit = {
val a = List(1,2,3)
val c = a.filter(x => x % 2 == 0)
println(c)
}
}
3.5.sortBy指定字段排序
3.5.1.【结论】作用
遍历存取有序的数组、集合与其他可迭代对象,将每个元素按指定字段排序,排序后的所有元素装入新对象进行返回,返回值类型 = 原可迭代对象
3.5.2.方法本法
def sortBy[B](f:A => B): Ordering[B]
# 说明:
0.方法的泛型:
[B],排序字段的数据类型
1.方法的参数
f:A => B,代表接收一个函数对象,函数的参数是可迭代对象的类型A,函数返回值类型是B
2.方法的返回值
Ordering[B],方法的返回值是B类型的集合,可省略不写
3.5.3.【结论】使用示例
object SortBy {
def main(args: Array[String]): Unit = {
val list1 = List("01 hadoop", "05 flume", "03 hive", "04 spark")
val list2 = list1.sortBy(x => x.split(" ")(0))
println(list2) // 效果:List(01 hadoop, 03 hive, 04 spark, 05 flume)
}
}
3.6.sortWith自定义排序
3.6.1.【结论】作用
遍历存取有序的数组、集合与其他可迭代对象,将每个元素按函数的规则排序,排序后的所有元素装入新对象进行返回,返回值类型 = 原可迭代对象
3.6.2.方法本法
def sortWith(lt: (A, A) => Boolean): Ordering[A]
# 说明:
0.方法的参数
lt: (A, A) => Boolean,代表接收一个函数对象lt,函数的第1个参数是当前元素,是可迭代对象的类型A,函数的第2个参数是下一个元素,是可迭代对象的类型A,函数返回值类型是这俩参数比大小的结果Boolean
1.方法的返回值
Ordering[A],方法的返回值是B类型的集合,可省略不写
3.6.3.【结论】使用示例
object SortBy {
def main(args: Array[String]): Unit = {
val list1 = List(2,3,1,6,4,5)
val list2 = list1.sortWith((x, y) => x > y)
println(list2) // 效果:List(01 hadoop, 03 hive, 04 spark, 05 flume)
}
}
3.7.groupBy分组
3.7.1.【结论】作用
遍历数组、集合与其他可迭代对象,将每个元素按指定字段分组,分组结果装入新对象进行返回,返回值类型 = Map(分组字段值1->原迭代对象数据类型(原元素1, 原元素2), 分组字段值2->原迭代对象数据类型(原元素3, 原元素4))
3.7.2.方法本法
def groupBy[K](f: A => K): immutable.Map[K, Repr]
# 说明:
0.方法的泛型
[K],分组字段的类型
1.方法的参数
f: A => K,代表接收一个函数对象f,函数的参数是当前元素,是可迭代对象的类型A,函数返回值类型分组字段的类型
2.方法的返回值
immutable.Map[K, Repr],方法的返回值不可变map,key是分组字段,类型是K,value装了所有符合key的一组元素,类型是原可迭代对象的类型,返回值可省略不写
3.7.3.【结论】使用示例
# 需求:
有一个列表,包含了学生的姓名和性别: "刘德华" -> "男", "刘亦菲" -> "女", "胡歌" -> "男"
请按照性别进行分组
统计不同性别的学生人数
# 实现:
object GroupBy {
def main(args: Array[String]): Unit = {
val list1 = List("刘德华" -> "男", "刘亦菲" -> "女", "胡歌" -> "男")
val list2 = list1.groupBy(x => x._2)
println(list2) // 效果:Map(男 -> List((刘德华,男), (胡歌,男)), 女 -> List((刘亦菲,女)))
val list3 = list2.map(x => x._1 -> x._2.size)
println(list3) // 效果:Map(男 -> 2, 女 -> 1)
}
}
3.8.reduce聚合
3.8.1.【结论】作用
遍历数组、集合与其他可迭代对象,将所有元素合并为1个,结果装入新对象进行返回,返回值类型 = 可迭代对象的元素的类型
3.8.2.方法本法
def reduce[A1 >: A](op: (A1, A1) => A1): A1
# 说明:
0.方法的泛型
[A1 >: A],(下界)A1必须是可迭代对象的元素类型的父类, 或者和可迭代对象的元素类型相同
1.方法的参数
op: (A1, A1) => A1,代表接收一个函数对象op,函数的第一个A1类型参数是当前聚合后的变量,第二个A1类型参数是当前要进行聚合的元素,函数返回值是A1类型的,最终聚合为一个元素
2.方法的返回值
A1,可省略不写
# 注意:
0.reduce和reduceLeft效果一致,表示从左到右计算
1.reduceRight表示从右到左计算
3.8.3.【结论】使用示例
object Reduce {
def main(args: Array[String]): Unit = {
val l1 = List(1,2,3,4,5)
val l2 = l1.reduce((x, y) => x + y)
println(l2)
}
}
3.9.fold折叠
3.9.1.【结论】作用
遍历数组、集合与其他可迭代对象,基于初始值,将所有元素合并为1个,结果装入新对象进行返回,返回值类型 = 可迭代对象的元素的类型
3.9.2.方法本法
def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1
# 说明:
0.方法的泛型
[A1 >: A],(下界)A1必须是可迭代对象的元素类型的父类, 或者和可迭代对象的元素类型相同
1.方法的参数
参数1:z: A1,代表初始值,基于此进行运算
参数2:op: (A1, A1) => A1,代表接收一个函数对象op,函数的第一个A1类型参数是当前聚合后的变量,第二个A1类型参数是当前要进行聚合的元素,函数返回值是A1类型的,最终聚合为一个元素
2.方法的返回值
A1,可省略不写
# 注意:
0.fold和foldLet效果一致,表示从左往右计算
1.foldRight表示从右往左计算
3.9.3.【结论】使用示例
object Fold {
def main(args: Array[String]): Unit = {
val l1 = List(1,2,3,4,5)
val l2 = l1.fold(10)((x, y) => x + y)
println(l2) // 效果:25
}
}