$02[Scala(函数式编程)]

第一章.函数式编程

面向对象编程:

  • 解决问题,分解对象,行为,属性,然后通过对象的关系以及行为的调用来解决问题
  • 对象: 用户
  • 行为: 登录,连接Jdbc,读取数据库
  • 属性: 用户名,密码
  • Scala语言是一个完全面向对象编程语言,万物皆对象

函数式编程:

  • 解决问题时,将问题分解成一个一个的步骤,将每个步骤进行封装(函数),通过调用这些封装好的步骤,解决问题
  • 例如: 请求->用户名,密码->连接jdbc->读取数据库

在Scala中函数式编程和面向对象编程融合在一起了

1.方法定义语法

package com.atguigu.chapter05

object $01_MethodDefined {
  /**
   * 方法定义语法: def 方法名(参数名:参数类型,....):返回值类型={方法体}
   */
  def main(args:Array[String]): Unit={
    println(add(10,20))
  }
  def add(x:Int,y:Int):Int={
    x+y
  }

}

2.方法简化的原则

package com.atguigu.chapter05

object $02_MethodSample {
  /**
   * 方法简化的原则:
   *    1.如果方法使用方法体的块表达式的结果值作为方法的返回值,此时定义方法的时候方法的返回值类型可以省略
   *      注意:如果方法体中有return关键字,方法的返回值类型必须定义
   *    2.如果方法体只有一行语句,那么方法体的{}可以忽略
   *    3.如果方法不需要返回值,那么定义方法的时候=可以忽略  [=与{}不能同时忽略]
   */
  def main(args:Array[String]):Unit={
    println(add2(10,20))
    println(add3(10,20))
    printMsg2("hello")
    //1.如果定义方法的时候没有(),那么在调用方法的时候()也不能带上
    hello2
    //2.如果定义方法的时候有(),那么在调用方法的时候()可有可无
    hello()
    hello
  }

  //标准定义形式
  def add(x:Int,y:Int):Int={
    return x + y
  }
  //1.如果方法使用方法体的块表达式的结果值作为方法的返回值,此时定义方法的时候,方法的返回值类型可以忽略
  def add2(x:Int,y:Int)={
    x + y
  }
  //2.如果方法体只有一行语句,那么方法体的{}可以忽略
  def add3(x:Int,y:Int) = x + y

  //标准形式
  def printMsg(msg:String):Unit={
    println(s"msg=${msg}")
  }
  //3.如果方法不需要返回值,那么定义方法的时候=可以忽略[=与{}不能同时忽略]
  def printMsg2(msg:String){
    println(s"msg=${msg}")
  }
  //标准形式
  def hello():Unit={
    println("hello...........")
  }
  //4.如果方法不需要参数,那么定义方法的时候()可以忽略
  def hello2{
    println("hello2...........")
  }

}

3.方法参数

object $03_MethodParam {
  /**
   * scala方法的参数
   *    1.默认值参数,在调用方法的时候有默认值的参数可以不用传参数[默认值参数一般放在参数列表最后面]
   *        语法: def 方法名(参数名:类型[默认值],.....):返回值类型 = {方法体}
   *    2.带名参数:在调用方法的时候指定将参数值传给哪个参数
   *    3.可变参数:在调用方法的时候传递的参数的个数不固定
   *        语法: def 方法名(参数名:类型,...,参数名:类型*):返回值类型={方法体}
   *        scala可变参数不能直接传递集合,如果想要将集合所有元素传递给可变参数,可以通过 集合名:_*的方式传递
   */
    def main(args:Array[String]):Unit ={
      println(add(10))
      //带名参数
      println(add(x=4,y=6))
      val arr = Array[Int](10,20,30,40)
      println(sum(10,20,arr:_*))
    }




  //默认值参数
  def add(x:Int,y:Int=30) = x + y
  //可变参数
  def sum(x:Int,y:Int,z:Int*) = x + y + z.sum

}

需求: 统计前七天的用户注册数

object demo{

  //需求:统计前七天的用户注册数
  def main(args: Array[String]): Unit = {
    val paths = getPaths(7, "/user/hive/warehouse/user_info")
    println(paths)

    println("----------------------------------")
    readPaths(paths)
  }

  def getPaths(n:Int,pathPrefix:String)={
    //获取当前日期
    val currentDate = LocalDateTime.now()
    for(i<-1 to n) yield{
      //日期加减法
      val time = currentDate.plusDays(-i)
      //格式化时间
      val timeStr = time.format(DateTimeFormatter.ofPattern("yyyyMMdd"))
      s"${pathPrefix}/${timeStr}"
    }
  }

  def readPaths(paths:IndexedSeq[String]):Unit={
    for (path <- paths) {
      println(path)
    }
  }


}

4.函数定义语法

package com.atguigu.chapter05

object $04_FunctionDefiend {

  /**
   * 方法就是函数,函数也是对象
   * 函数的定义语法: val 函数名 = (参数名:参数类型,...) => {函数体}
   * 函数的简化:如果函数体中只有一行语句,那么函数体{}可以忽略
   * 函数是对象,函数的类型:(参数类型,....)=>返回值类型
   *
   */

  def main(args: Array[String]): Unit = {
    println(func(10,20))
    println(func.apply(10,20))
    val name2 = name
    val func3 = func
    hello()
    println(hello)
    println(func3(30,40))

  }

  val func=(x:Int,y:Int) => {x + y}
  val name:String = "zhangsan"
  val hello=()=>{
    println("...........")
  }
  
  val func2 = new Function2[Int,Int,Int]{
    override def apply(v1:Int,v2:Int):Int=v1+v2
    
  }


}

5.方法与函数的区别

package com.atguigu.chapter05

object $05_MethodAndFunction {
  /**
   * 方法与函数的区别
   *      1.方法定义在类中的时候可以重载,函数是对象,函数名就是对象的引用,所以不能重载
   *      2.方法存储在方法区中,函数是对象存储在堆中
   * 方法和函数的关系
   *      1.方法名可以转成函数,可以通过 方法名 _ 的方式转成函数
   *      2.方法如果定义在方法中就是函数,不能重载的
   */
  def main(args: Array[String]): Unit = {
     println(func(10,20))
    println(add(10,20,30))
    //方法转函数
    val func2 = add _
    println(func2(10,20,30))

  }

  val func = (x:Int,y:Int)=>x + y
  // func = (x:Int,y:Int,z:Int)=>x + y + z
  //def add(x:Int,y:Int)= x+y
  def add(x:Int,y:Int,z:Int) = x + y + z

}

6.高阶函数的定义

package com.atguigu.chapter05

object $06_HIghFunction {
  /**
   * 高阶函数:以函数作为参数或者返回值的方法/函数称之为高阶函数
   *
   */
  def main(args: Array[String]): Unit = {
    val func =(x:Int,y:Int)=>{
      x + y
    }
    println(add(10,20,func))
  }

  //高阶函数
  def add(x:Int,y:Int,func:(Int,Int)=>Int)={
    func(x,y)
  }

}

7.高阶函数的简化

package com.atguigu.chapter05

object $07_HightFunctionSample {
  /**
   * 高阶函数的简化:
   *    1.可以直接将函数的值传给参数
   *    2.函数的参数类型可以省略
   *    3.如果函数的参数在函数体中只使用了一次可以用_代替
   *          注意:以下情况下不能以_代替
   *          1.函数体中参数的使用顺序与定义顺序不一致的时候不能用_代替[第N个下划线代表函数第N个参数]<针对函数有多个参数的情况>
   *          2.如果函数只有一个参数,在函数体中没有做任何操作,直接返回参数本身,此时不能用_代替<针对函数只有一个参数的情况>
   *          3.如果函数的参数体中有嵌套,函数的参数在嵌套中以表达式存在,此时不能用_简化
   *    4.如果函数只有一个参数,函数的参数列表的()可以省略
   */
  def main(args: Array[String]): Unit = {
    val func = (x:Int,y:Int) => x * y
    println(add(10,20,func))
    //1.可以直接将函数的值传给参数
    println(add(10,20,(x:Int,y:Int)=>x * y))
    //2.函数的参数类型可以省略
    println(add(10,20,(x,y)=>x * y))
    //3.如果函数的参数在函数体中只使用了一次可以用_代替
    println(add(10,20,_ * _))
    //
    println(add(10,20,(x,y)=>y-x))
    //1.函数体中参数的使用顺序与定义顺序不一致时不能用_代替
    //println(add(10,20,_-_))
    //2.如果函数只有一个参数,在函数体中没有做任何操作,直接返回函数本身,此时不能用_代替
    println(add2(10,(x:Int)=>x))
    //println(add2(10,_))
    //3.如果函数体中有嵌套,函数的参数在嵌套中以表达式形式存在,此时不能用_代替
    println(add2(10,(x:Int)=>(x+1)*10))
    //println(add2(10,(_+1)*10))
    //4.如果函数只有一个参数,函数的参数列表的()可以省略
    println(add2(10,x=>(x+1)*10))
  }
  def add(x:Int,y:Int,func:(Int,Int)=>Int)={
    func(x,y)
  }
  def add2(x:Int,func:Int=>Int) =func(x)
}

8.匿名函数

package com.atguigu.chapter05

object $08_NoNameFunction {
  /**
   * 匿名函数:没有函数名的函数称之为匿名函数
   * 匿名函数一般不单独使用,一般作为高阶函数的参数值传递
   *
   */
  def main(args: Array[String]): Unit = {
      val func = (x:Int) => x+10
    println(func(20))
    println(add(100,func))
    //匿名函数一般不单独使用,一般作为高阶函数的参数值传递
    println(add(100,_+10))

  }
  def add(x:Int,func:Int=>Int)=func(x)

}

9.递归

package com.atguigu.chapter05

object $09_Recursion {
  /**
   * 递归:自己调用自己
   * 递归必须满足两个条件:
   *     1.必须要有退出条件
   *     2.必须定义返回值类型
   */
  def main(args: Array[String]): Unit = {
    println(func(5))
    println(m1(5))

  }
  val func:Int =>Int=(n:Int)=>{
    if(n==1) 1
    else n * func(n-1)
  }
  /*val func=(n:Int) =>{
    if(n==1) 1
    else n * func(n-1)
  }*/
  def m1(n:Int):Int={
    //必须有退出条件
    if(n==1) 1
    else n * m1(n-1)
  }
}

10.柯里化

package com.atguigu.chapter05

object $10_Currying {
  /**
   * 柯里化:有多个参数列表的方法称之为柯里化
   */
  def main(args: Array[String]): Unit = {
    println(m1(10,20)(30)(40))
    println(m2(10,20,30,40))

  }


  /**
   * 柯里化
   */
  def m1(x:Int,y:Int)(z:Int)(a:Int)=x+y+z+a

  def m2(x:Int,y:Int,z:Int,a:Int)=x+y+z+a
}

11.闭包

package com.atguigu.chapter05

object $11_ClosePackage {
  /**
   * 闭包:函数体中使用了外部变量的函数称之为闭包
   */

  def main(args: Array[String]): Unit = {
    println(func(10))
  }
  val y =20
  //闭包函数
  val func =(x:Int)=>{
    x + y
  }

}

12.惰性求值

package com.atguigu.chapter05

object $12_Lazy {
  /**
   * 惰性求值:只有变量在真正使用的时候才会初始化
   * 语法:lazy val 变量名:类型 = 值
   */
  def main(args: Array[String]): Unit = {
    val name = "zhangsan"
    println(s"name=${name}")
    lazy val age =20
    println(s"age=${age}")
  }
}

13.控制抽象

package com.atguigu.chapter05

object $18_ControlAbstract {
  /**
   * 控制抽象:
   * 语法:  => 返回值类型
   * 控制抽象不能单独使用,只能作为方法的参数类型存在
   * 控制抽象其实就是一个块表达式,后续可以当做函数调用,只是在调用控制抽象时不能带上()
   */
  def main(args: Array[String]): Unit = {
     val a ={
       println("---------------")
       10+20
     }
    m1(a)
    m1(a)
    m1(a)
      val func=()=>{
        println("=====================")
        10+20
      }
    m2(func)
    m2(func)
    m2(func)

    m3({
      println("***************")
      10+20
    })
  }
  def m1(x:Int) =x * x
  def m2(func:()=>Int)= func() * func()
  def m3(func: =>Int)={
    func
    func
    func
  }

}

第二章.练习

1.练习一

需求:根据指定规则对数组中的每个元素操作
数据: Array[String]("hello","spark","java","hadoop")
规则: 获取每个元素的长度 [可变]
结果: Array[Int](5,5,4,6)
package com.atguigu.chapter05

object $13_HomeWork01 {
  /*
  * 需求: 根据指定规则对数组中的每个元素操作

- 数据: Array[String]("hello","spark","java","hadoop")
- 规则: 获取每个元素的长度 [可变]
- 结果: Array[Int](5,5,4,6)
  * */
  def main(args: Array[String]): Unit = {
    val data = Array[String]("hello","spark","java","hadoop")
    val func = (x:String) =>x.length
    val arr = map(data,func)
    println(arr.toList)

  }

  def map(data:Array[String],func:String => Any)={
    for(element<-data) yield{
      func(element)
    }
  }

}

2.练习二

根据指定规则对数组进行过滤
数据: Array[Int](1,4,3,7,6,10,9)
规则: 保留偶数数据 [可变]
结果: Array[Int](4,6,10)
package com.atguigu.chapter05

object $14_HomeWork02 {
  /**
   * 根据指定规则对数组进行过滤
     数据: Array[Int](1,4,3,7,6,10,9)
     规则: 保留偶数数据 [可变]
     结果: Array[Int](4,6,10)
   */
  def main(args: Array[String]): Unit = {
    val data = Array[Int](1, 4, 3, 7, 6, 10, 9)
    
    val func = (data:Array[Int]) => {
      val arr = data.filter(x => x%2==0)
       arr.toList
      

    }
    val result = map(data,func)

    println(result)
  }

  def map(data:Array[Int],func:Array[Int]=>Any)={
    func(data)
  }
  

}

3.练习三

根据指定规则对数组所有元素进行聚合
数据: Array[Int](1,4,3,7,6,10,9)
规则: 求和 [可变]
结果: 40
package com.atguigu.chapter05

object $15_HomeWork03 {
  /**
   * 根据指定规则对数组所有元素进行聚合
     数据: Array[Int](1,4,3,7,6,10,9)
     规则: 求和 [可变]
     结果: 40
   */
  def main(args: Array[String]): Unit = {
       val sum =0
       val data= Array[Int](1,4,3,7,6,10,9)
       val func=(data:Array[Int])=>data.sum
       val result = map(data,func)
       println(result)

  }
     def map(data:Array[Int],func:Array[Int]=>Int)={
          func(data)
     }

}

4.练习四

根据指定规则对数组中的元素进行分组
数据: Array[String]("zhangsan man shenzhen","lisi woman beijing","zhaoliu man beijing")
规则: 按照性别分组 [可变]
结果: Map( man-> List( "zhangsan man shenzhen", "zhaoliu man beijing") , woman -> List( "lisi woman beijing" ) )
package com.atguigu.chapter05

import java.util

object $16_HomeWork04 {

  /**
   * 根据指定规则对数组中的元素进行分组
    数据: Array[String]("zhangsan man shenzhen","lisi woman beijing","zhaoliu man beijing")
    规则: 按照性别分组 [可变]
    结果: Map( man-> List( "zhangsan man shenzhen", "zhaoliu man beijing") , woman -> List( "lisi woman beijing" ) )
   */
  def main(args: Array[String]): Unit = {
      val data = Array[String]( "zhangsan man shenzhen","lisi woman beijing","zhaoliu man beijing")
      val func =(x:String)=>x.split(" ")(1)
      println(groupBy(data, func))

  }
    def groupBy(data:Array[String],func:String=>Any)={
        //定义一个容器装载分组的结果
        val map = new util.HashMap[Any,util.List[String]]()
        //遍历
        for(element<-data){
            //得到分组的key
            val key = func(element)
            //判断key是否存在,如果存在则直接将当前元素添加到key对应的list中
            if(map.containsKey(key)){
                val list = map.get(key)
                list.add(element)
            }
            if(!map.containsKey(key)){
                val list = new util.ArrayList[String]()
                list.add(element)
                map.put(key,list)
            }
        }
        map
    }

}

5.练习五

根据指定规则获取数组中的最大值的信息
数据: Array[String]("zhangsan 20 1500","lisi 35 2000","zhaoliu 18 4500")
规则: 获取年龄最大的人的信息 [可变]
结果: "lisi 35 2000"
package com.atguigu.chapter05

object $17_HomeWork05 {
  /*根据指定规则获取数组中的最大值的信息
  数据: Array[String]("zhangsan 20 1500","lisi 35 2000","zhaoliu 18 4500")
  规则: 获取年龄最大的人的信息 [可变]
  结果: "lisi 35 2000"*/
  def main(args: Array[String]): Unit = {
    val data = Array[String]("zhangsan 20 1500", "lisi 35 2000", "zhaoliu 18 4500")
    val func = (x: String) => {
      x.split(" ")(1).toInt

    }
    println(maxBy(data, func))


  }

  def maxBy(data:Array[String],func:String=>Int)={
    //定义中间变量
    var tmp = func(data(0))
    var result:String = null
    for (elem <- data) {
      val key = func(elem)
      if(key >= tmp){
        tmp = key
        result =elem
      }
    }
    result
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值