Scala基础(二)

函数式编程

方法

  1. 对象:

    封装数据

  2. 方法:步骤的封装

方法定义方式:

  def 方法名(参数名:参数类型,…………):返回值类型={
  	方法体
  } 
  1. 方法的简化

    1. 方法体中的语句只有一句可以省略{},类似Java中的if省略一句的情况
    2. 由于存在自动类型推断,可以省略方法中的返回值(但最后一句必须是可以作为返回值的表达式或结果值)
      • 如果方法体中有return,必须确定返回值类型
    3. 如果方法不需要参数,那么在方法定义时可以省略参数列表的()
      • 省略()后,调用该方法时,不能带上()
      • 没省略()时,调用该方法时,可以带上(),也可以不带()
    4. 方法不需要返回值时,可以在定义方法时,省略=
      1. 需注意的是,=和{}不能同时省略
  2. 方法的参数

    1. 默认值参数:定义方法时,对参数默认值进行了赋值。在调用时,可以不对参数赋值(即使用默认值)
    2. 带名参数:结合默认参数,在调用方法时,对特定参数进行了新的赋值(带名带的是定义方法时的参数名)
    3. 可变参数:类似Java中的可变形参,参数的个数不固定
      1. 语法:def 方法名(参数名:类型,……,参数:类型*):返回值类型={}
    4. 注意:
      1. 可变参数不能与默认值参数一起使用
        1. 可变参数必须在形参列表的末尾
          1. 可变参数不能直接传递数组,想要传递一个集合给可变参数,需要通过 集合名:_* 的方式传递

函数

  1. 函数的定义

  • val 函数名 = (参数名:类型,...) => { 函数体 }
    • 函数的返回值默认就是函数体块表达式的结果值
    • 函数是对象,
      • 函数的类型: (参数类型,...) => 返回值类型
    • val 变量名:变量类型 = 变量值
  1. 函数的简化

  • 如果函数体的{}中只有一个语句,{}可以省略

方法和函数

  1. 区别
    1. 方法如果定义在class/Object中都可以重载,函数是对象,故函数不可以重载
    2. 方法存储在方法区中;函数是对象,对象是存储在堆中
  2. 联系
    1. 方法如果定义在方法中,此时方法就是函数,不能进行重载
      • 比如定义一个方法A在main方法中,此时方法A就是一个函数
    2. 手动将方法转换为函数:方法名 _ (下划线前有空格)

高阶函数

  1. 定义

​ 以函数作为参数/函数/返回值的方法

  1. 简化(调用高阶函数时才能简化)

    1. 直接传递函数的值
    2. 函数的参数类型可以省略
    3. 如果函数的参数在函数体中只使用了一次,那么可以使用占位符_代替
      • 以下几种情况不能使用占位符
        1. 如果函数的参数使用顺序与定义顺序不一致,此时不能使用下划线简化【第几个下划线就代表第几个参数】《只针对有多个参数的情况》
        2. 如果函数体中有嵌套,函数的参数在嵌套中以表达式的形式存在,此时不能使用下划线简化《针对函数体中有嵌套的情况》
        3. 如果函数只有一个参数,在函数体中没有进行任何操作直接返回参数时,此时也不能使用下划线简化《针对函数只有一个参数的情况》
    4. 如果函数只有一个参数,那么函数的参数列表()可以省略

匿名函数

  1. 定义:

    • 没有函数名的函数,常用于给高阶函数传参
  2. 声明方式

    • 就是高阶函数中缩略了函数名的函数。

函数柯里化

  1. 说明

    • 将一个接收多个参数的函数转化成一个接受一个参数的函数过程,可以简单的理解为一种特殊的参数列表声明方式。
  2. 算式推导

     //目标式
     def add( x:Int,y:Int )(z:Int)(a:Int) = x+y+z+a
    
      /**
        * 柯里化演变过程
        */
      def m1(x:Int,y:Int) = {
    
        val func = (z:Int) => {
    
          val f1 = (a:Int) => {
              x+y+z+a
          }
    
          f1
        }
    
        func
      }
    

闭包

  1. 定义

    • 函数体中使用了不属于函数本身的变量的情况称之为闭包。即:一个函数和与其相关的引用环境(变量)组合的一个整体(实体)
//外部变量
var z: Int = 10

//闭包
def f(y: Int): Int = {
      z + y
}

递归

定义

  • 一个函数/方法在函数/方法体内又调用了本身,我们称之为递归调用

条件

  1. 有退出
  2. 必须定义返回值类型
  3. 函数的递归不能写在方法内部(因为函数是一个对象,需要创建了才能使用)

惰性求值

  1. 语法:lazy val 变量名 = 值

    def main(args:
    Array[String]): Unit = {
        lazy val res = sum(10, 30)
        println("----------------")
        println("res=" + res)
    }
    val sum =(n1: Int, n2: Int)=> {
        println("sum被执行。。。")
        return n1 + n2
    }
    
    
    结果:
    ----------------
    sum被执行。。。
    res=40
    
  2. 注意:lazy标识的变量只有在使用的时候才会初始化,没有使用之前不会初始化。(类似Java中的懒汉式设计模式)需要注意的是,惰性求值只适用于函数上,当然方法也可以转换为函数。

控制抽象

  1. 语法: =>返回值类型
  2. 注意:
    • 控制抽象不能单独使用,只能作为方法的参数存在
    • 控制抽象其实就是一个<块表达式>,控制抽象中返回值类型就是<块表达式>的结果值类型,后续看到方法的参数类型是控制抽象的时候,其实就是让你传一个块表达式。
    • 控制抽象可以当做函数调用,调用的时候不能带上(),否则调用一次,控制抽象的块表达式就执行一次
上一篇:深入分析Spark UDF的性能


下一篇:scala语言