首页
学习
活动
专区
圈层
工具
发布
50 篇文章
1
Hadoop面试复习系列——HDFS(一)
2
大数据技术之_04_Hadoop学习_01_HDFS_HDFS概述+HDFS的Shell操作(开发重点)+HDFS客户端操作(开发重点)+HDFS的数据流(面试重点)+NameNode和Seconda
3
大数据技术之_05_Hadoop学习_02_MapReduce_MapReduce框架原理+InputFormat数据输入+MapReduce工作流程(面试重点)+Shuffle机制(面试重点)
4
大数据技术之_05_Hadoop学习_01_MapReduce_MapReduce概述+Hadoop序列化
5
大数据技术之_03_Hadoop学习_01_入门_大数据概论+从Hadoop框架讨论大数据生态+Hadoop运行环境搭建(开发重点)
6
大数据技术之_05_Hadoop学习_04_MapReduce_Hadoop企业优化(重中之重)+HDFS小文件优化方法+MapReduce扩展案例+倒排索引案例(多job串联)+TopN案例+找博客
7
大数据技术之_06_Zookeeper学习_Zookeeper入门+Zookeeper安装+Zookeeper内部原理+Zookeeper实战(开发重点)+企业面试真题
8
大数据技术之_09_Hive学习_复习与总结
9
大数据技术之_07_Hadoop学习_HDFS_HA(高可用)_HA概述+HDFS-HA工作机制+HDFS-HA集群配置+YARN-HA配置+HDFS Federation(联邦) 架构设计
10
大数据技术之_08_Hive学习_01_Hive入门+Hive安装、配置和使用+Hive数据类型
11
大数据技术之_08_Hive学习_04_压缩和存储(Hive高级)+ 企业级调优(Hive优化)
12
大数据技术之_08_Hive学习_05_Hive实战之谷粒影音(ETL+TopN)+常见错误及解决方案
13
大数据技术之_08_Hive学习_02_DDL数据定义(创建/查询/修改/删除数据库+创建表+分区表+修改表+删除表)+DML数据操作(数据导入+数据导出+清除表中数据)
14
大数据技术之_08_Hive学习_03_查询+函数
15
大数据技术之_16_Scala学习_09_函数式编程-高级
16
大数据技术之_09_Flume学习_Flume概述+Flume快速入门+Flume企业开发案例+Flume监控之Ganglia+Flume高级之自定义MySQLSource+Flume企业真实面试题(
17
大数据技术之_13_Azkaban学习_Azkaban(阿兹卡班)介绍 + Azkaban 安装部署 + Azkaban 实战
18
大数据技术之_19_Spark学习_07_Spark 性能调优 + 数据倾斜调优 + 运行资源调优 + 程序开发调优 + Shuffle 调优 + GC 调优 + Spark 企业应用案例
19
大数据技术之_12_Sqoop学习_Sqoop 简介+Sqoop 原理+Sqoop 安装+Sqoop 的简单使用案例+Sqoop 一些常用命令及参数
20
大数据技术之_16_Scala学习_13_Scala语言的数据结构和算法_Scala学习之旅收官之作
21
大数据技术之_19_Spark学习_06_Spark 源码解析 + Spark 通信架构、脚本解析、standalone 模式启动、提交流程 + Spark Shuffle 过程 + Spark 内存
22
大数据技术之_16_Scala学习_04_函数式编程-基础+面向对象编程-基础
23
大数据技术之_14_Oozie学习
24
大数据技术之_26_交通状态预测项目_01
25
大数据技术之_16_Scala学习_02_变量
26
大数据技术之_16_Scala学习_07_数据结构(上)-集合
27
大数据技术之_28_电商推荐系统项目_01
28
大数据技术之_28_电商推荐系统项目_02
29
大数据技术之_18_大数据离线平台_04_数据分析 + Hive 之 hourly 分析 + 常用 Maven 仓库地址
30
大数据技术之_16_Scala学习_01_Scala 语言概述
31
大数据技术之_29_MySQL 高級面试重点串讲_02
32
大数据技术之_18_大数据离线平台_05_离线平台项目模块小结
33
大数据技术之_19_Spark学习_06_Spark 源码解析小结
34
大数据技术之_16_Scala学习_05_面向对象编程-中级
35
大数据技术之_16_Scala学习_08_数据结构(下)-集合操作+模式匹配
36
大数据技术之_24_电影推荐系统项目_05_项目系统设计
37
大数据技术之_19_Spark学习_03_Spark SQL 应用解析小结
38
大数据技术之_19_Spark学习_07_Spark 性能调优小结
39
大数据技术之_19_Spark学习_05_Spark GraphX 应用解析小结
40
大数据技术之_19_Spark学习_02_Spark Core 应用解析小结
41
大数据技术之_24_电影推荐系统项目_08_项目总结及补充
42
大数据技术之_19_Spark学习_01_Spark 基础解析小结(无图片)
43
大数据技术之_18_大数据离线平台_03_数据处理+工具代码导入+业务 ETL 实现+创建数据库表
44
大数据技术之_24_电影推荐系统项目_02_Python 基础语法复习
45
大数据技术之_24_电影推荐系统项目_06_项目体系架构设计 + 工具环境搭建 + 创建项目并初始化业务数据 + 离线推荐服务建设 + 实时推荐服务建设 + 基于内容的推荐服务建设
46
大数据技术之_27_电商平台数据分析项目_01_大数据的框架回顾 + 大数据的企业应用
47
大数据技术之_23_Python核心基础学习_03_函数 + 对象(12.5小时)
48
大数据技术之_32_大数据面试题_01_Hive 基本面试 + Hive 数据分析面试 + Flume + Kafka 面试
49
大数据技术之_23_Python核心基础学习_04_ 异常 + 文件(3.5小时)
50
大数据技术之_16_Scala学习_03_运算符+程序流程控制
清单首页hadoop文章详情

大数据技术之_16_Scala学习_09_函数式编程-高级

第十三章 函数式编程-高级13.1 偏函数(partial function)13.1.1 提出一个需求,引出思考13.1.2 解决方式-filter + map 返回新的集合13.1.3 解决方式-模式匹配13.1.4 偏函数的基本介绍13.1.5 偏函数的快速入门13.1.6 偏函数的小结13.1.7 偏函数的简写形式13.2 作为参数的函数13.3 匿名函数13.4 高阶函数(higher-order function)13.5 参数(类型)推断13.6 闭包(closure)13.7 函数柯里化(curry)13.8 控制抽象函数


第十三章 函数式编程-高级

13.1 偏函数(partial function)

13.1.1 提出一个需求,引出思考

给你一个集合 val list = List(1, 2, 3, 4, "abc"),请完成如下要求: 1、将集合 list 中的所有数字 +1,并返回一个新的集合。 2、要求忽略掉 非数字 的元素,即返回的 新的集合 形式为 (2, 3, 4, 5)。

13.1.2 解决方式-filter + map 返回新的集合

13.1.3 解决方式-模式匹配

两种方式的示例代码如下: 示例代码如下:

代码语言:javascript
复制
package com.atguigu.chapter13

/**
  * 给你一个集合 val list = List(1, 2, 3, 4, "abc"),请完成如下要求:
  * 1、将集合 list 中的所有数字 +1,并返回一个新的集合。
  * 2、要求忽略掉 非数字 的元素,即返回的 新的集合 形式为 (2, 3, 4, 5)。
  */
object PartialFunDemo01 {
  def main(args: Array[String]): Unit = {
    // 思路1:filter + map 方式解决
    // 虽然可以解决问题,但是麻烦。
    val list = List(1, 2, 3, 4, "abc")
    // 先过滤,再map
    list.filter(f1)
    println(list.filter(f1).map(f2).map(f3)) // List(2, 3, 4, 5)

    // 思路2:模式匹配
    // 小结:虽然使用模式匹配比较简单,但是不够完美。
    val list2 = list.map(addOne2)
    println(list2) // List(2, 3, 4, 5, ())
  }

  // 模式匹配
  def addOne2(i: Any): Any = {
    i match {
      case x:Int => x + 1
      case _ =>
    }
  }

  // 将 List 转为 Any
  def f1(n: Any): Boolean = {
    n.isInstanceOf[Int]
  }

  // 将 Any 转为 Int [map]
  def f2(n: Any): Int = {
    n.asInstanceOf[Int]
  }

  def f3(n: Int): Int = {
    n + 1
  }
}

输出结果如下:

代码语言:javascript
复制
List(2, 3, 4, 5)
List(2, 3, 4, 5, ())

13.1.4 偏函数的基本介绍

13.1.5 偏函数的快速入门

示例代码如下:

代码语言:javascript
复制
package com.atguigu.chapter13

object PartialFunDemo02 {
  def main(args: Array[String]): Unit = {
    // 使用偏函数解决
    val list = List(1, 2, 3, 4, "hello")
    // 定义一个偏函数
    // 1. PartialFunction[Any, Int] 表示偏函数接收的参数类型是 Any,返回的类型是 Int
    // 2. isDefinedAt(x: Any) 如果返回 true,就会去调用 apply 构建对象实例,如果是 false,就过滤
    // 3. apply 构造器,对传入的值 + 1,并返回(新的集合)
    val addOne3 = new PartialFunction[Any, Int] {
      def isDefinedAt(any: Any) = if (any.isInstanceOf[Int]) true else false
      def apply(any: Any) = any.asInstanceOf[Int] + 1 // 将 any 显示转换成 Int
    }

    // 使用偏函数
    // 说明:如果是使用偏函数,则不能使用 map,应该使用 collect
    // 说明偏函数的执行流程
    // 1. 遍历 list 集合的所有元素
    // 2. 然后调用 val element = if(partialFun-isDefinedAt(list单个元素)) {partialFun-apply(list单个元素)}
    // 3. 每得到一个符合要求的元素 element,放入到新的集合,最后返回
    val list3 = list.collect(addOne3)
    println(list3) // List(2, 3, 4, 5)
  }
}

输出结果如下:

代码语言:javascript
复制
List(2, 3, 4, 5)

13.1.6 偏函数的小结

13.1.7 偏函数的简写形式

示例代码如下:

代码语言:javascript
复制
package com.atguigu.chapter13

/**
  * 偏函数简化形式
  */
object PartialFunDemo03 {
  def main(args: Array[String]): Unit = {
    // 使用偏函数的简化形式解决
    // 第一种简写形式:
    def f2: PartialFunction[Any, Int] = {
      case i: Int => i + 1 // case 语句可以自动转换为偏函数
      case j: Double => (j * 2).toInt
    }

    val list2 = List(1, 2, 3, 4, 5.6, "hello").collect(f2)
    println(list2) // List(2, 3, 4, 5, 11)

    // 第二种简写形式:
    val list3 = List(1, 2, 3, 4, "ABC").collect { case i: Int => i + 1 }
    println(list3) // List(2, 3, 4, 5)
  }
}

输出结果如下:

代码语言:javascript
复制
List(2, 3, 4, 5, 11)
List(2, 3, 4, 5)

13.2 作为参数的函数

1、基本介绍

2、快速入门案例 示例代码如下:

代码语言:javascript
复制
package com.atguigu.chapter13

object FunParameterDemo01 {
  def main(args: Array[String]): Unit = {
    def plus(x: Int) = 3 + x
    val result1 = Array(1, 2, 3, 4).map(plus(_))
    println(result1.mkString(",")) // (4,5,6,7)

    // 1. 在 scala 中,函数也是有类型,比如 plus 就是 <function1>
    println("puls的函数类型是" + (plus _))

  }
}

输出结果如下:

代码语言:javascript
复制
4,5,6,7
puls的函数类型是<function1>

3、应用案例小结

13.3 匿名函数

1、基本介绍

2、快速入门案例 示例代码如下:

代码语言:javascript
复制
package com.atguigu.chapter13

object AnonymouseFunctionDemo01 {
  def main(args: Array[String]): Unit = {
    // 对匿名函数的说明
    // 1. 不需要写 def 函数名
    // 2. 不需要写返回类型,使用类型推导
    // 3. =  变成  =>
    // 4. 如果有多行,则使用 {} 包括
    val triple = (x: Double) => 3 * x
    println(triple) // <function1>
    println(triple(3)) // 9.0
  }
}

输出结果如下:

代码语言:javascript
复制
<function1>
9.0

3、练习题 请编写一个匿名函数,可以返回2个整数的和,并输出该匿名函数的类型。 示例代码如下:

代码语言:javascript
复制
    val f1 = (n1: Int, n2: Int ) => {
      println("匿名函数被调用")
      n1 + n2
    }
    println("f1类型=" + f1) // f1类型=<function2>
    println(f1(10, 30)) // 40

13.4 高阶函数(higher-order function)

1、基本介绍   能够接受函数作为参数的函数,叫做高阶函数 (higher-order function)。可使应用程序更加健壮。 2、高阶函数基本使用案例

扩展代码如下:

代码语言:javascript
复制
package com.atguigu.chapter13

object HigherOrderFunctionDemo01 {
  def main(args: Array[String]): Unit = {
    // test 就是一个高阶函数,它可以接收 f: Double => Double 和 f1: Double => Int
    def test(f: Double => Double, f1: Double => Int, n1: Double) = {
      f(f1(n1))
    }

    // sum 是接收一个 Double,返回一个 Double
    def sum(d: Double): Double = {
      d + d
    }

    def mod(d: Double): Int = {
      d.toInt % 2
    }

    val res = test(sum, mod, 5.0)
    println("res=" + res) // 2.0
  }
}

输出结果如下:

代码语言:javascript
复制
res=2.0

3、高阶函数可以返回函数类型 示例代码如下:

代码语言:javascript
复制
package com.atguigu.chapter13

object HigherOrderFunctionDemo02 {
  def main(args: Array[String]): Unit = {
    // 说明
    // 1. minusxy 是高阶函数,因为它返回匿名函数
    // 2. 返回的匿名函数是 (y: Int) => x - y
    // 3. 返回的匿名函数可以使用变量接收
    def minusxy(x: Int) = {
      (y: Int) => x - y // 匿名函数
    }

    // 分步执行
    // f1 就是 (y: Int) => 3 - y
    val f1 = minusxy(3)
    println("f1的类型=" + f1)
    println(f1(1)) // 2
    println(f1(9)) // -6

    // 也可以一步到位的调用(函数柯里化)
    println(minusxy(4)(9)) // -5
  }
}

输出结果如下:

代码语言:javascript
复制
f1的类型=<function1>
2
-6
-5

13.5 参数(类型)推断

1、基本介绍

2、应用案例 示例代码如下:

代码语言:javascript
复制
package com.atguigu.chapter13

object ParameterInferDemo01 {
  def main(args: Array[String]): Unit = {

    val list = List(1, 2, 3, 4)
    println(list.map((x: Int) => x + 1)) // (2,3,4,5)
    println(list.map((x) => x + 1)) // (2,3,4,5) 参数类型是可以推断时,可以省略参数类型。
    println(list.map(x => x + 1)) // (2,3,4,5) 当传入的函数,只有单个参数时,可以省去括号。
    println(list.map(_ + 1)) // (2,3,4,5) 如果变量只在=>右边只出现一次,可以用_来代替。

    println(list.reduce(f1)) // 10
    println(list.reduce((n1: Int, n2: Int) => n1 + n2)) // 10
    println(list.reduce((n1, n2) => n1 + n2)) // 10
    println(list.reduce(_ + _)) // 10
  }

  def f1(n1: Int, n2: Int): Int = {
    n1 + n2
  }
}

输出结果如下:

代码语言:javascript
复制
List(2, 3, 4, 5)
List(2, 3, 4, 5)
List(2, 3, 4, 5)
List(2, 3, 4, 5)
10
10
10
10

3、应用案例小结

13.6 闭包(closure)

1、基本介绍

2、应用案例小结

3、闭包的最佳实践 示例代码如下:

代码语言:javascript
复制
package com.atguigu.chapter13

/**
  * 请编写一个程序,具体要求如下:
  * 编写一个函数 makeSuffix(suffix: String) 可以接收一个文件后缀名(比如.jpg),并返回一个闭包
  * 调用闭包,可以传入一个文件名,如果该文件名没有指定的后缀(比如.jpg),则返回 文件名.jpg,如果已经有.jpg后缀,则返回原文件名。
  * 要求使用闭包的方式完成。
  * String.endsWith(xx)
  */
object ClosureDemo01 {
  def main(args: Array[String]): Unit = {
    // 使用并测试
    val f = makeSuffix(".jpg")
    println(f("dog.jpg")) // dog.jpg
    println(f("cat")) // cat.jpg

  }

  // 自定义的函数
  def makeSuffix(suffix: String) = {
    // 返回一个匿名函数,该匿名函数会使用外部函数的suffix,那么该函数和suffix整体形成一个闭包。
    (filename: String) => {
      if (filename.endsWith(suffix)) {
        filename
      } else {
        filename + suffix
      }
    }
  }
}

输出结果如下:

代码语言:javascript
复制
dog.jpg
cat.jpg

4、闭包的好处

13.7 函数柯里化(curry)

1、基本介绍

2、函数柯里化快速入门案例

3、函数柯里化最佳实践

示例代码如下:

代码语言:javascript
复制
package com.atguigu.chapter13

/**
  * 函数柯里化最佳实践
  * 比较两个字符串在忽略大小写的情况下是否相等,注意,这里是两个任务:
  * 全部转大写(或小写)
  * 比较是否相等
  * 针对这两个操作,我们用一个函数去处理的思想,其实也变成了两个函数处理的思想(柯里化)
  */
object CurryDemo02 {
  def main(args: Array[String]): Unit = {
    // 方式1:简单的方式,使用一个函数完成
    def eq(s1: String)(s2: String): Boolean = {
      s1.toLowerCase == s2.toLowerCase
    }
    println(eq("hello")("HELLO"))

    // 方式2:使用稍微高级的用法(隐式类):形式为 str.方法()
    def eq2(s1: String, s2: String): Boolean = {
      s1.equals(s2)
    }
    // 隐式类:该隐式类扩展了String对象的功能
    implicit class TestEq(s: String) {
      // 体现了将比较字符串的事情,分解成两个任务完成:
      // 任务1:checkEq 完转换大小写
      // 任务2.:f函数完成比较任务
      def checkEq(ss: String)(f: (String, String) => Boolean): Boolean = {
        f(s.toLowerCase, ss.toLowerCase)
      }
    }
    val str1 = "hello"
    println(str1.checkEq("HeLLO")(eq2))

    // 方式2的简化写法
    str1.checkEq("HeLLO")((s1: String, s2: String) => { s1.equals(s2) })
    str1.checkEq("HeLLO")((s1: String, s2: String) => s1.equals(s2)) // 代码块只有一行代码时。可以省略{}
    str1.checkEq("HeLLO")((s1, s2) => s1.equals(s2)) // 参数类型是可以推断时,可以省略参数类型。
    str1.checkEq("HeLLO")(_.equals(_)) // 如果变量只在=>右边只出现一次,可以用_来代替。
  }
}

输出结果如下:

代码语言:javascript
复制
true
true

13.8 控制抽象函数

1、看一个需求

2、控制抽象基本介绍

3、快速入门案例 示例代码如下:

代码语言:javascript
复制
package com.atguigu.chapter13

object AbstractControlDemo01 {
  def main(args: Array[String]): Unit = {
    // myRunInThread 就是一个抽象控制函数,其参数是没有输入,也没有输出的函数 f1: () => Unit
    def myRunInThread(f1: () => Unit) = {
      new Thread {
        override def run(): Unit = {
          f1()
        }
      }.start()
    }

    myRunInThread {
      () =>
        println("干活咯!5秒完成...")
        Thread.sleep(5000)
        println("干完咯!")
    }

    // 简写形式
    def myRunInThread2(f1: => Unit) = {
      new Thread {
        override def run(): Unit = {
          f1
        }
      }.start()
    }

    // 对于没有输入,也没有返回值函数,可以简写成如下形式:
    myRunInThread2 {
      println("干活咯!5秒完成...~~~")
      Thread.sleep(5000)
      println("干完咯!~~~")
    }

  }
}

4、进阶用法:实现类似 while 的 mywhile 函数 示例代码如下:

代码语言:javascript
复制
package com.atguigu.chapter13

object AbstractControlDemo02 {
  def main(args: Array[String]): Unit = {
    var x = 10
    while (x > 0) {
      x -= 1
      println("x=" + x)
    }

    // 说明:实现类似 while 的 mywhile 函数
    // 1 函数名为 mywhile,实现了类似 while 循环的效果
    // 2. condition: => Boolean 是一个没有输入值,返回 Boolean 类型函数
    // 3. block: => Unit 没有输入值,也没有返回值的函数
    def mywhile(condition: => Boolean)(block: => Unit): Unit = {
      // 类似 while 循环,递归
      if (condition) {
        block // x=9 x=8 x=7 ...
        mywhile(condition)(block)
      }
    }

    x = 10
    mywhile(x > 0) {
      x -= 1
      println("x=" + x)
    }

  }
}

输出结果如下:

代码语言:javascript
复制
x=9
x=8
x=7
x=6
x=5
x=4
x=3
x=2
x=1
x=0
-----
x=9
x=8
x=7
x=6
x=5
x=4
x=3
x=2
x=1
x=0
下一篇
举报
领券