第一章.函数式编程
面向对象编程:
- 解决问题,分解对象,行为,属性,然后通过对象的关系以及行为的调用来解决问题
- 对象: 用户
- 行为: 登录,连接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
}
}