第一章.函数式编程

面向对象编程:

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

函数式编程:

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

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

1.方法定义语法

  1. package com.atguigu.chapter05
  2. object $01_MethodDefined {
  3. /**
  4. * 方法定义语法: def 方法名(参数名:参数类型,....):返回值类型={方法体}
  5. */
  6. def main(args:Array[String]): Unit={
  7. println(add(10,20))
  8. }
  9. def add(x:Int,y:Int):Int={
  10. x+y
  11. }
  12. }

2.方法简化的原则

  1. package com.atguigu.chapter05
  2. object $02_MethodSample {
  3. /**
  4. * 方法简化的原则:
  5. * 1.如果方法使用方法体的块表达式的结果值作为方法的返回值,此时定义方法的时候方法的返回值类型可以省略
  6. * 注意:如果方法体中有return关键字,方法的返回值类型必须定义
  7. * 2.如果方法体只有一行语句,那么方法体的{}可以忽略
  8. * 3.如果方法不需要返回值,那么定义方法的时候=可以忽略 [=与{}不能同时忽略]
  9. */
  10. def main(args:Array[String]):Unit={
  11. println(add2(10,20))
  12. println(add3(10,20))
  13. printMsg2("hello")
  14. //1.如果定义方法的时候没有(),那么在调用方法的时候()也不能带上
  15. hello2
  16. //2.如果定义方法的时候有(),那么在调用方法的时候()可有可无
  17. hello()
  18. hello
  19. }
  20. //标准定义形式
  21. def add(x:Int,y:Int):Int={
  22. return x + y
  23. }
  24. //1.如果方法使用方法体的块表达式的结果值作为方法的返回值,此时定义方法的时候,方法的返回值类型可以忽略
  25. def add2(x:Int,y:Int)={
  26. x + y
  27. }
  28. //2.如果方法体只有一行语句,那么方法体的{}可以忽略
  29. def add3(x:Int,y:Int) = x + y
  30. //标准形式
  31. def printMsg(msg:String):Unit={
  32. println(s"msg=${msg}")
  33. }
  34. //3.如果方法不需要返回值,那么定义方法的时候=可以忽略[=与{}不能同时忽略]
  35. def printMsg2(msg:String){
  36. println(s"msg=${msg}")
  37. }
  38. //标准形式
  39. def hello():Unit={
  40. println("hello...........")
  41. }
  42. //4.如果方法不需要参数,那么定义方法的时候()可以忽略
  43. def hello2{
  44. println("hello2...........")
  45. }
  46. }

3.方法参数

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

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

  1. object demo{
  2. //需求:统计前七天的用户注册数
  3. def main(args: Array[String]): Unit = {
  4. val paths = getPaths(7, "/user/hive/warehouse/user_info")
  5. println(paths)
  6. println("----------------------------------")
  7. readPaths(paths)
  8. }
  9. def getPaths(n:Int,pathPrefix:String)={
  10. //获取当前日期
  11. val currentDate = LocalDateTime.now()
  12. for(i<-1 to n) yield{
  13. //日期加减法
  14. val time = currentDate.plusDays(-i)
  15. //格式化时间
  16. val timeStr = time.format(DateTimeFormatter.ofPattern("yyyyMMdd"))
  17. s"${pathPrefix}/${timeStr}"
  18. }
  19. }
  20. def readPaths(paths:IndexedSeq[String]):Unit={
  21. for (path <- paths) {
  22. println(path)
  23. }
  24. }
  25. }

4.函数定义语法

  1. package com.atguigu.chapter05
  2. object $04_FunctionDefiend {
  3. /**
  4. * 方法就是函数,函数也是对象
  5. * 函数的定义语法: val 函数名 = (参数名:参数类型,...) => {函数体}
  6. * 函数的简化:如果函数体中只有一行语句,那么函数体{}可以忽略
  7. * 函数是对象,函数的类型:(参数类型,....)=>返回值类型
  8. *
  9. */
  10. def main(args: Array[String]): Unit = {
  11. println(func(10,20))
  12. println(func.apply(10,20))
  13. val name2 = name
  14. val func3 = func
  15. hello()
  16. println(hello)
  17. println(func3(30,40))
  18. }
  19. val func=(x:Int,y:Int) => {x + y}
  20. val name:String = "zhangsan"
  21. val hello=()=>{
  22. println("...........")
  23. }
  24. val func2 = new Function2[Int,Int,Int]{
  25. override def apply(v1:Int,v2:Int):Int=v1+v2
  26. }
  27. }

5.方法与函数的区别

  1. package com.atguigu.chapter05
  2. object $05_MethodAndFunction {
  3. /**
  4. * 方法与函数的区别
  5. * 1.方法定义在类中的时候可以重载,函数是对象,函数名就是对象的引用,所以不能重载
  6. * 2.方法存储在方法区中,函数是对象存储在堆中
  7. * 方法和函数的关系
  8. * 1.方法名可以转成函数,可以通过 方法名 _ 的方式转成函数
  9. * 2.方法如果定义在方法中就是函数,不能重载的
  10. */
  11. def main(args: Array[String]): Unit = {
  12. println(func(10,20))
  13. println(add(10,20,30))
  14. //方法转函数
  15. val func2 = add _
  16. println(func2(10,20,30))
  17. }
  18. val func = (x:Int,y:Int)=>x + y
  19. // func = (x:Int,y:Int,z:Int)=>x + y + z
  20. //def add(x:Int,y:Int)= x+y
  21. def add(x:Int,y:Int,z:Int) = x + y + z
  22. }

6.高阶函数的定义

  1. package com.atguigu.chapter05
  2. object $06_HIghFunction {
  3. /**
  4. * 高阶函数:以函数作为参数或者返回值的方法/函数称之为高阶函数
  5. *
  6. */
  7. def main(args: Array[String]): Unit = {
  8. val func =(x:Int,y:Int)=>{
  9. x + y
  10. }
  11. println(add(10,20,func))
  12. }
  13. //高阶函数
  14. def add(x:Int,y:Int,func:(Int,Int)=>Int)={
  15. func(x,y)
  16. }
  17. }

7.高阶函数的简化

  1. package com.atguigu.chapter05
  2. object $07_HightFunctionSample {
  3. /**
  4. * 高阶函数的简化:
  5. * 1.可以直接将函数的值传给参数
  6. * 2.函数的参数类型可以省略
  7. * 3.如果函数的参数在函数体中只使用了一次可以用_代替
  8. * 注意:以下情况下不能以_代替
  9. * 1.函数体中参数的使用顺序与定义顺序不一致的时候不能用_代替[第N个下划线代表函数第N个参数]<针对函数有多个参数的情况>
  10. * 2.如果函数只有一个参数,在函数体中没有做任何操作,直接返回参数本身,此时不能用_代替<针对函数只有一个参数的情况>
  11. * 3.如果函数的参数体中有嵌套,函数的参数在嵌套中以表达式存在,此时不能用_简化
  12. * 4.如果函数只有一个参数,函数的参数列表的()可以省略
  13. */
  14. def main(args: Array[String]): Unit = {
  15. val func = (x:Int,y:Int) => x * y
  16. println(add(10,20,func))
  17. //1.可以直接将函数的值传给参数
  18. println(add(10,20,(x:Int,y:Int)=>x * y))
  19. //2.函数的参数类型可以省略
  20. println(add(10,20,(x,y)=>x * y))
  21. //3.如果函数的参数在函数体中只使用了一次可以用_代替
  22. println(add(10,20,_ * _))
  23. //
  24. println(add(10,20,(x,y)=>y-x))
  25. //1.函数体中参数的使用顺序与定义顺序不一致时不能用_代替
  26. //println(add(10,20,_-_))
  27. //2.如果函数只有一个参数,在函数体中没有做任何操作,直接返回函数本身,此时不能用_代替
  28. println(add2(10,(x:Int)=>x))
  29. //println(add2(10,_))
  30. //3.如果函数体中有嵌套,函数的参数在嵌套中以表达式形式存在,此时不能用_代替
  31. println(add2(10,(x:Int)=>(x+1)*10))
  32. //println(add2(10,(_+1)*10))
  33. //4.如果函数只有一个参数,函数的参数列表的()可以省略
  34. println(add2(10,x=>(x+1)*10))
  35. }
  36. def add(x:Int,y:Int,func:(Int,Int)=>Int)={
  37. func(x,y)
  38. }
  39. def add2(x:Int,func:Int=>Int) =func(x)
  40. }

8.匿名函数

  1. package com.atguigu.chapter05
  2. object $08_NoNameFunction {
  3. /**
  4. * 匿名函数:没有函数名的函数称之为匿名函数
  5. * 匿名函数一般不单独使用,一般作为高阶函数的参数值传递
  6. *
  7. */
  8. def main(args: Array[String]): Unit = {
  9. val func = (x:Int) => x+10
  10. println(func(20))
  11. println(add(100,func))
  12. //匿名函数一般不单独使用,一般作为高阶函数的参数值传递
  13. println(add(100,_+10))
  14. }
  15. def add(x:Int,func:Int=>Int)=func(x)
  16. }

9.递归

  1. package com.atguigu.chapter05
  2. object $09_Recursion {
  3. /**
  4. * 递归:自己调用自己
  5. * 递归必须满足两个条件:
  6. * 1.必须要有退出条件
  7. * 2.必须定义返回值类型
  8. */
  9. def main(args: Array[String]): Unit = {
  10. println(func(5))
  11. println(m1(5))
  12. }
  13. val func:Int =>Int=(n:Int)=>{
  14. if(n==1) 1
  15. else n * func(n-1)
  16. }
  17. /*val func=(n:Int) =>{
  18. if(n==1) 1
  19. else n * func(n-1)
  20. }*/
  21. def m1(n:Int):Int={
  22. //必须有退出条件
  23. if(n==1) 1
  24. else n * m1(n-1)
  25. }
  26. }

10.柯里化

  1. package com.atguigu.chapter05
  2. object $10_Currying {
  3. /**
  4. * 柯里化:有多个参数列表的方法称之为柯里化
  5. */
  6. def main(args: Array[String]): Unit = {
  7. println(m1(10,20)(30)(40))
  8. println(m2(10,20,30,40))
  9. }
  10. /**
  11. * 柯里化
  12. */
  13. def m1(x:Int,y:Int)(z:Int)(a:Int)=x+y+z+a
  14. def m2(x:Int,y:Int,z:Int,a:Int)=x+y+z+a
  15. }

11.闭包

  1. package com.atguigu.chapter05
  2. object $11_ClosePackage {
  3. /**
  4. * 闭包:函数体中使用了外部变量的函数称之为闭包
  5. */
  6. def main(args: Array[String]): Unit = {
  7. println(func(10))
  8. }
  9. val y =20
  10. //闭包函数
  11. val func =(x:Int)=>{
  12. x + y
  13. }
  14. }

12.惰性求值

  1. package com.atguigu.chapter05
  2. object $12_Lazy {
  3. /**
  4. * 惰性求值:只有变量在真正使用的时候才会初始化
  5. * 语法:lazy val 变量名:类型 = 值
  6. */
  7. def main(args: Array[String]): Unit = {
  8. val name = "zhangsan"
  9. println(s"name=${name}")
  10. lazy val age =20
  11. println(s"age=${age}")
  12. }
  13. }

13.控制抽象

  1. package com.atguigu.chapter05
  2. object $18_ControlAbstract {
  3. /**
  4. * 控制抽象:
  5. * 语法: => 返回值类型
  6. * 控制抽象不能单独使用,只能作为方法的参数类型存在
  7. * 控制抽象其实就是一个块表达式,后续可以当做函数调用,只是在调用控制抽象时不能带上()
  8. */
  9. def main(args: Array[String]): Unit = {
  10. val a ={
  11. println("---------------")
  12. 10+20
  13. }
  14. m1(a)
  15. m1(a)
  16. m1(a)
  17. val func=()=>{
  18. println("=====================")
  19. 10+20
  20. }
  21. m2(func)
  22. m2(func)
  23. m2(func)
  24. m3({
  25. println("***************")
  26. 10+20
  27. })
  28. }
  29. def m1(x:Int) =x * x
  30. def m2(func:()=>Int)= func() * func()
  31. def m3(func: =>Int)={
  32. func
  33. func
  34. func
  35. }
  36. }

第二章.练习

1.练习一

  1. 需求:根据指定规则对数组中的每个元素操作
  2. 数据: Array[String]("hello","spark","java","hadoop")
  3. 规则: 获取每个元素的长度 [可变]
  4. 结果: Array[Int](5,5,4,6)
  1. package com.atguigu.chapter05
  2. object $13_HomeWork01 {
  3. /*
  4. * 需求: 根据指定规则对数组中的每个元素操作
  5. - 数据: Array[String]("hello","spark","java","hadoop")
  6. - 规则: 获取每个元素的长度 [可变]
  7. - 结果: Array[Int](5,5,4,6)
  8. * */
  9. def main(args: Array[String]): Unit = {
  10. val data = Array[String]("hello","spark","java","hadoop")
  11. val func = (x:String) =>x.length
  12. val arr = map(data,func)
  13. println(arr.toList)
  14. }
  15. def map(data:Array[String],func:String => Any)={
  16. for(element<-data) yield{
  17. func(element)
  18. }
  19. }
  20. }

2.练习二

  1. 根据指定规则对数组进行过滤
  2. 数据: Array[Int](1,4,3,7,6,10,9)
  3. 规则: 保留偶数数据 [可变]
  4. 结果: Array[Int](4,6,10)
  1. package com.atguigu.chapter05
  2. object $14_HomeWork02 {
  3. /**
  4. * 根据指定规则对数组进行过滤
  5. 数据: Array[Int](1,4,3,7,6,10,9)
  6. 规则: 保留偶数数据 [可变]
  7. 结果: Array[Int](4,6,10)
  8. */
  9. def main(args: Array[String]): Unit = {
  10. val data = Array[Int](1, 4, 3, 7, 6, 10, 9)
  11. val func = (data:Array[Int]) => {
  12. val arr = data.filter(x => x%2==0)
  13. arr.toList
  14. }
  15. val result = map(data,func)
  16. println(result)
  17. }
  18. def map(data:Array[Int],func:Array[Int]=>Any)={
  19. func(data)
  20. }
  21. }

3.练习三

  1. 根据指定规则对数组所有元素进行聚合
  2. 数据: Array[Int](1,4,3,7,6,10,9)
  3. 规则: 求和 [可变]
  4. 结果: 40
  1. package com.atguigu.chapter05
  2. object $15_HomeWork03 {
  3. /**
  4. * 根据指定规则对数组所有元素进行聚合
  5. 数据: Array[Int](1,4,3,7,6,10,9)
  6. 规则: 求和 [可变]
  7. 结果: 40
  8. */
  9. def main(args: Array[String]): Unit = {
  10. val sum =0
  11. val data= Array[Int](1,4,3,7,6,10,9)
  12. val func=(data:Array[Int])=>data.sum
  13. val result = map(data,func)
  14. println(result)
  15. }
  16. def map(data:Array[Int],func:Array[Int]=>Int)={
  17. func(data)
  18. }
  19. }

4.练习四

  1. 根据指定规则对数组中的元素进行分组
  2. 数据: Array[String]("zhangsan man shenzhen","lisi woman beijing","zhaoliu man beijing")
  3. 规则: 按照性别分组 [可变]
  4. 结果: Map( man-> List( "zhangsan man shenzhen", "zhaoliu man beijing") , woman -> List( "lisi woman beijing" ) )
  1. package com.atguigu.chapter05
  2. import java.util
  3. object $16_HomeWork04 {
  4. /**
  5. * 根据指定规则对数组中的元素进行分组
  6. 数据: Array[String]("zhangsan man shenzhen","lisi woman beijing","zhaoliu man beijing")
  7. 规则: 按照性别分组 [可变]
  8. 结果: Map( man-> List( "zhangsan man shenzhen", "zhaoliu man beijing") , woman -> List( "lisi woman beijing" ) )
  9. */
  10. def main(args: Array[String]): Unit = {
  11. val data = Array[String]( "zhangsan man shenzhen","lisi woman beijing","zhaoliu man beijing")
  12. val func =(x:String)=>x.split(" ")(1)
  13. println(groupBy(data, func))
  14. }
  15. def groupBy(data:Array[String],func:String=>Any)={
  16. //定义一个容器装载分组的结果
  17. val map = new util.HashMap[Any,util.List[String]]()
  18. //遍历
  19. for(element<-data){
  20. //得到分组的key
  21. val key = func(element)
  22. //判断key是否存在,如果存在则直接将当前元素添加到key对应的list中
  23. if(map.containsKey(key)){
  24. val list = map.get(key)
  25. list.add(element)
  26. }
  27. if(!map.containsKey(key)){
  28. val list = new util.ArrayList[String]()
  29. list.add(element)
  30. map.put(key,list)
  31. }
  32. }
  33. map
  34. }
  35. }

5.练习五

  1. 根据指定规则获取数组中的最大值的信息
  2. 数据: Array[String]("zhangsan 20 1500","lisi 35 2000","zhaoliu 18 4500")
  3. 规则: 获取年龄最大的人的信息 [可变]
  4. 结果: "lisi 35 2000"
  1. package com.atguigu.chapter05
  2. object $17_HomeWork05 {
  3. /*根据指定规则获取数组中的最大值的信息
  4. 数据: Array[String]("zhangsan 20 1500","lisi 35 2000","zhaoliu 18 4500")
  5. 规则: 获取年龄最大的人的信息 [可变]
  6. 结果: "lisi 35 2000"*/
  7. def main(args: Array[String]): Unit = {
  8. val data = Array[String]("zhangsan 20 1500", "lisi 35 2000", "zhaoliu 18 4500")
  9. val func = (x: String) => {
  10. x.split(" ")(1).toInt
  11. }
  12. println(maxBy(data, func))
  13. }
  14. def maxBy(data:Array[String],func:String=>Int)={
  15. //定义中间变量
  16. var tmp = func(data(0))
  17. var result:String = null
  18. for (elem <- data) {
  19. val key = func(elem)
  20. if(key >= tmp){
  21. tmp = key
  22. result =elem
  23. }
  24. }
  25. result
  26. }
  27. }