• Scala系列-2、scala函数式编程


    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    传送门:大数据系列文章目录
    在这里插入图片描述

    所谓函数式编程, 主要指的是, 在调用一个方法的时候, 可以将函数作为一个方法的参数, 传递到方法中, 这样的操作称为函数式编程, 在scala中提供了非常的可以支持函数式编程的方法

    • 遍历(foreach
    • 映射(map
    • 映射扁平化(flatmap
    • 过滤(filter
    • 是否存在(exists
    • 排序(sortedsortBysortWith
    • 分组(groupBy
    • 聚合计算(reduce
    • 折叠(fold

    注意: 习惯性将支持函数式编程的方法, 称为算子

    foreach算子

    foreach算子主要的作用 : 用于对集合进行遍历操作

    调用方法的参数传递的格式

    foreach(f: (A)Unit): Unit
    
    • 1

    示例

    有一个列表,包含以下元素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)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    在这里插入图片描述

    映射 | map 算子

    MR 中 map的作用是什么?当然是接收 k1和v1 负责将其转换为 k2和v2

    在scala中 map算子 主要负责将数据进行一对一的转换操作, 在转换的时候, 执行一些转换操作, 特点输入进去几个值, 就会输出几个值

    格式:

    def map[B](f: (A) ⇒ B): TraversableOnce[B]
    
    • 1

    案例一

    1. 创建一个列表,包含元素1,2,3,4
    2. 对List中的每一个元素加1
    val list1  = List(1,2,3,4)
    
    
    list1.map( i => i+1 )
    
    简写:
    list1.map( _+1 )
    
    输出: 
    List(2,3,4,5)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    扁平化映射 | flatMap

    功能: 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(张三, 李四, 王五, 赵六, 田七, 周八)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    过滤 | filter

    作用: 对数据进行过滤, 将符合条件的数据获取出来即可

    格式:

    def filter(p: (A)Boolean): TraversableOce[A]
    
    表示 : 在函数中进行数据判断, 如果判断为true 表示需要此数据, 如果为false 表示此数据直接过滤掉
    
    • 1
    • 2
    • 3

    示例

    将 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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    排序操作: 指定字段排序 | sortBy

    作用: 根据字段的进行排序的操作

    格式:

    def sortBy[B](f: (A) ⇒ B): List[A]
    
    • 1

    示例:

    比如 目前有这么一份数据:

    ​ “张三 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
    
    • 1
    • 2
    • 3
    • 4
    • 5

    排序操作: 自定义排序 | sortWith

    作用: 自定义其排序内容

    格式:

    def sortWith(lt: (A, A)Boolean): List[A]
    
    注意:
    	在自定义排序中, 参数是有两个值, 这个两个值就是列表中相邻的两个元素, 对元素进行两两比较, 然后进行比较处理即可
    
    • 1
    • 2
    • 3
    • 4

    示例:

    1. 有一个列表,包含以下元素:2,3,1,6,4,5
    2. 使用sortWith对列表进行降序排序

    val list4 = List(2,3,1,6,4,5)

    list4.sortWith( (a1,a2) => a1 > a2 )

    简写:
    list4.sortWith( _ < _ )

    分组 | groupBy

    作用: 根据指定的字段执行分组操作, 将相同组的数据放置在一起

    格式:

    def groupBy[K](f: (A) ⇒ K): Map[K, List[A]]
    
    • 1

    示例:

    比如目前有一份单词数据: 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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    聚合操作 | reduce

    作用: 帮助实现聚合操作, 注意此聚合不含分组操作

    格式:

    def reduce[A1 >: A](op: (A1, A1) ⇒ A1): A1
    扩展:
    	reduceLeft  此方法与  reduce一致的 都是从左往右计算聚合
    	reduceRight  从右往左计算聚合
    	
    说明:
    	此方法, 需要传递的函数具备两个参数: 
    			参数1: 局部累加聚合结果
    			参数2: 每一次遍历出来的元素
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    示例

    1. 定义一个列表,包含以下元素:1,2,3,4,5,6,7,8,9,10
    2. 使用reduce计算所有元素的和
    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(_+_)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    聚合操作 | fold

    作用: 与reduce是一致的, 只比reduce的操作多了一个初始值

    格式:

    def fold[A1 >: A](z: A1)(op: (A1, A1) ⇒ A1): A1
    
    • 1

    示例

    1. 定义一个列表,包含以下元素:1,2,3,4,5,6,7,8,9,10
    2. 使用reduce计算所有元素的和
    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初始值, 默认情况下, 初始值是集合的第一个元素
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
  • 相关阅读:
    企业注销的债权债务如何处理
    Android-Firebase合规问题解决方案-详细攻略,debug模式破解难题
    VM系列振弦采集读数模块的测量模式
    LeetCode 509 斐波那契数(动态规划)
    学习笔记7--交通环境行为预测
    独立站谷歌付费广告关键词选词技巧实操
    前后端分离解决跨域问题
    整理mongodb文档:副本集成员可以为偶数
    HMS Core机器学习服务实现同声传译,支持中英文互译和多种音色语音播报
    vue + el-checkbox 单选功能
  • 原文地址:https://blog.csdn.net/l848168/article/details/127805554