版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
传送门:大数据系列文章目录
所谓函数式编程, 主要指的是, 在调用一个方法的时候, 可以将函数作为一个方法的参数, 传递到方法中, 这样的操作称为函数式编程, 在scala中提供了非常的可以支持函数式编程的方法
foreach
)map
)flatmap
)filter
)exists
)sorted
、sortBy
、sortWith
)groupBy
)reduce
)fold
)注意: 习惯性将支持函数式编程的方法, 称为算子
foreach算子主要的作用 : 用于对集合进行遍历操作
调用方法的参数传递的格式
foreach(f: (A) ⇒ Unit): Unit
示例
有一个列表,包含以下元素1,2,3,4,请使用foreach方法遍历打印每个元素
val list1 = List(1,2,3,4)
基于for循环:
for( i <- list1 ) println(i)
基于foreach算子操作:
list1.foreach((i:Int) => println(i) );
其实通过函数传递的一般都是操作的规则, 具体要怎么做内容
以上操作是可以进行简写的:
1) 对于函数的参数类型, 一般是可以省略的, 因为在调用foreach方法时候, scala会自动推断类型
2) 如果函数的参数只有一个, () 也是可以省略的
list1.foreach( i => println(i) );
上述操作 依然还是可以进行简写:
1) 如果 参数在 函数体中仅使用了一次, 可以直接使用 _ 替代即可 , 不需要在定义变量了
list1.foreach( println(_) );
底层是如何实现的:
list1.foreach((i:Int) => println(i) );
def foreach ( val f1:Int => Unit ) { // f1 = (i:Int) => println(i)
for( i <- list1 ){
f1(i) // 定义规则
}
}
原始调用一个函数
val f1 = (i:Int) => println(i)
for(i <- list1 ){
f1(i)
}
MR 中 map的作用是什么?当然是接收 k1和v1 负责将其转换为 k2和v2
在scala中 map算子 主要负责将数据进行一对一的转换操作, 在转换的时候, 执行一些转换操作, 特点输入进去几个值, 就会输出几个值
格式:
def map[B](f: (A) ⇒ B): TraversableOnce[B]
案例一
val list1 = List(1,2,3,4)
list1.map( i => i+1 )
简写:
list1.map( _+1 )
输出:
List(2,3,4,5)
功能: flatMap 主要是用于将数据转换为另一种方式
此操作: 将 map 和 flatten 合并在一起的操作形式
示例1:
假设目前有这么一份数据:
“张三 李四”, “王五 赵六” , “田七 周八” , 需要转换为 张三 李四 王五 赵六 田七 周八
val list2 = List("张三 李四","王五 赵六","田七 周八")
原生写法:
list2.map(i => i.split(" ") )
结果:
res7: List[Array[String]] = List(Array(张三, 李四), Array(王五, 赵六), Array(田七, 周八))
res7.flatten
结果:
res8: List[String] = List(张三, 李四, 王五, 赵六, 田七, 周八)
以上两步 可以通过 flatMap解决:
list2.flatMap( i => i.split(" "))
简写:
list2.flatMap( _.split(" "))
结果内容:
res9: List[String] = List(张三, 李四, 王五, 赵六, 田七, 周八)
作用: 对数据进行过滤, 将符合条件的数据获取出来即可
格式:
def filter(p: (A) ⇒ Boolean): TraversableOce[A]
表示 : 在函数中进行数据判断, 如果判断为true 表示需要此数据, 如果为false 表示此数据直接过滤掉
示例
将 1~10之间的偶数获取出来
val list3 = 1 to 10;
list3.filter( i => if(i % 2 == 0) true else false )
简写:
list3.filter( i => i % 2 == 0 )
||
||
list3.filter( _ % 2 == 0)
作用: 根据字段的进行排序的操作
格式:
def sortBy[B](f: (A) ⇒ B): List[A]
示例:
比如 目前有这么一份数据:
“张三 20” “李四 15” “赵六 23” “田七 40” “周八 99”
要求请按照 年龄的升序排序
val list4 = List("张三 20","李四 15","赵六 23","田七 40","周八 99")
list4.sortBy( i => i.split(" ")(1))
list4.sortBy( i => i.split(" ")(1)).reverse
作用: 自定义其排序内容
格式:
def sortWith(lt: (A, A) ⇒ Boolean): List[A]
注意:
在自定义排序中, 参数是有两个值, 这个两个值就是列表中相邻的两个元素, 对元素进行两两比较, 然后进行比较处理即可
示例:
val list4 = List(2,3,1,6,4,5)
list4.sortWith( (a1,a2) => a1 > a2 )
简写:
list4.sortWith( _ < _ )
作用: 根据指定的字段执行分组操作, 将相同组的数据放置在一起
格式:
def groupBy[K](f: (A) ⇒ K): Map[K, List[A]]
示例:
比如目前有一份单词数据: hadoop hive hadoop sqoop hadoop hive hive hbase, 要求计算其每个单词的出现次数
val list5 = List("hadoop hive hadoop sqoop hadoop hive hive hbase")
操作:
list5.flatMap( i => i.split(" "))
结果:
res24: List[String] = List(hadoop, hive, hadoop, sqoop, hadoop, hive, hive, hbase)
res24.map(i => i -> 1 )
结果:
res25: List[(String, Int)] = List((hadoop,1), (hive,1), (hadoop,1), (sqoop,1), (hadoop,1), (hive,1), (hive,1), (hbase,1))
res25.groupBy(i =>i._1)
结果:
res26: scala.collection.immutable.Map[String,List[(String, Int)]] = Map(hadoop -> List((hadoop,1), (hadoop,1), (hadoop,1)), sqoop -> List((sqoop,1)), hive -> List((hive,1), (hive,1), (hive,1)), hbase -> List((hbase,1)))
res26.map( i => i._1 -> i._2.size )
结果:
res27: scala.collection.immutable.Map[String,Int] = Map(hadoop -> 3, sqoop -> 1, hive -> 3, hbase -> 1)
进行合并操作:
list5.flatMap( i => i.split(" ")).map(i => i -> 1 ).groupBy(i =>i._1).map( i => i._1 -> i._2.size )
进行简写:
list5.flatMap( _.split(" ")).map(_ -> 1 ).groupBy(_._1).map( i => i._1 -> i._2.size )
结果:
res28: scala.collection.immutable.Map[String,Int] = Map(hadoop -> 3, sqoop -> 1, hive -> 3, hbase -> 1)
作用: 帮助实现聚合操作, 注意此聚合不含分组操作
格式:
def reduce[A1 >: A](op: (A1, A1) ⇒ A1): A1
扩展:
reduceLeft 此方法与 reduce一致的 都是从左往右计算聚合
reduceRight 从右往左计算聚合
说明:
此方法, 需要传递的函数具备两个参数:
参数1: 局部累加聚合结果
参数2: 每一次遍历出来的元素
示例
val list6 = 1 to 10
list6.reduce((agg,curr) => agg + curr)
list6.reduce((agg,curr) => {
println(agg+" "+ curr)
agg + curr
})
scala> list6.reduce((agg,curr) => {
| println(agg+" "+ curr)
| agg + curr
| })
1 2
3 3
6 4
10 5
15 6
21 7
28 8
36 9
45 10
res34: Int = 55
简写:
list6.reduce(_+_)
作用: 与reduce是一致的, 只比reduce的操作多了一个初始值
格式:
def fold[A1 >: A](z: A1)(op: (A1, A1) ⇒ A1): A1
示例
val list6 = 1 to 10
list6.fold(100)((agg,curr) => agg + curr)
list6.fold(100)((agg,curr) => {
println(agg+" "+ curr)
agg + curr
})
100 1
101 2
103 3
106 4
110 5
115 6
121 7
128 8
136 9
145 10
res36: Int = 155
注意:
通过 fold 可以设置 agg初始值, 默认情况下, 初始值是集合的第一个元素