Scala函数的定义规则
1)定义方法的基本格式是:def 方法名称(参数列表):返回值类型 = {方法体}
def function1(param1: String, param2: String): String = {
"[" + param1 + "]" + ",[" + param2 + "]"
}
Note:
函数体中如果只有一行语句可以省略 {}
方法可以省略返回值类型;Scala提供了强大的类型推断功能、以及使用类型推断的时候两个限制
如果方法没有返回值可以使用Unit标注,类似于java的void 一旦方法使用了Unit 即使方法中有最后一条语句,也不返回。
/*定义的方法没有使用return关键字*/
def function1(param1: String, param2: String): String = {
"[" + param1 + "]" + ",[" + param2 + "]"
}
/*定义的方法使用return关键字*/
def function2(param1: String, param2: String): String = {
return "[" + param1 + "]" + ",[" + param2 + "]"
}
println(function1("Hello", "World"))
}
/*函数体中如果只含有一条语句可以省略 {}*/
def function3(a: Int, b: Int): Int = if (a > b) a else b;
/*自动类型推断功能有两个限制*/
/*1、如果使用return 关键字指定返回值 那么必须指定返回值的类型 否则编译错误*/
def function4(a: Int, b: Int): Int = {
if (a > b)
return a
else
return b
}
// def function5(a: Int, b: Int)= {
//
// if (a > b)
// return a
// else
// return b
// }
println(function4(4, 6));
// println(function5(4, 8));
// 2、函数的方法体中存在着递归调用 必须指定返回值类型
/* def function6(x: Int, y: Int) = {
if (x % y == 0)
y
else
function6(y, x % y)
}*/
//函数的返回值为空
def function7(a: Int, b: Int): Unit = {
if (a > b) {
a
} else {
b
}
}
print(function7(2, 3)) //()
2)spark开发中常用格式: def 方法名称:(参数列表类型)=>返回值类型={方法体中书写具体的参数名称}
def function8: (Int, Int, Int) => Int = {
(x, y, z) => {
x + y + z
}
}
3)柯里化
1、有一个函数,原来接受两个参数
2、现在我们将这个两个参数拆开
3、这样我们就得到了两个一个参数的函数了
4、这样我们调用的时候,就需要分别传入两个参数了
5、这样就叫柯里化
有多个参数列表的函数就是柯里化函数,所谓的参数列表就是用小括号括起来的函数参数列表。
柯里化函数定义:
def sum(x:Int)(y:Int) = x + y
或者
def add(x:Int)=(y:Int) => x+y
柯里化函数调用:add(1)(2)
//1) 函数的另一种定义方式:柯里化 def 函数名称(参数列表)(参数列表):返回值类型={函数体}
def function9(a: Int)(b: Int) = {
a + b
}
//函数的调用
println(function9(2)(4))
//2) 柯里化的另一种格式
def function10(a: Int) = (b: Int) => {
a + b
}
println(function10(2)(5))
4)可变参数的方法
Scala允许指定函数的最后一个参数可重复。 如 String* Int* 等。
// 可变参数的方法 当方法的参数个数不确定的时候 可以将方法的参数定义为可变的参数
// 可变的参数要求是方法的最后一个参数
def function14(name:String,nums:Int*): Unit ={
var sum=0
for(num -> nums){
sum+=num
}
println(name+"'"+"sum="+sum)
}
function14("yangshaojun",1,2,3,4,5)
def printString(args:String*)={
var i=0
for(arg <- args) {
println("args's ["+i+"]"+"value is "+arg)
i=i+1
}
}
使用序列调用变长函数
val s=function14(1 to 5 ) 是错误的。此时需要使用scala的特殊语法定义序列,让scala解释器能够识别,这种语法非常有用;在scala对的源码中大量的使用。
val s=functionn14(1 to 5 :_*)
5)方法的参数的默认值和带参数名称调用
方法的参数列表中的变量可以在定义方法的时候就去给他一个默认值
方法在调用的时候,赋值往往是从左到右赋值,也就是说需要将默认值放在方法参数的右边。
方法在调用的时候还可以指定参数的名字,这样就可以不考虑方法的参数的顺序了。
// 方法的默认参数和指定参数名调用
def function15(name: String, age: Int = 12, sex: String = "Man"): Unit = {
print("name=" + name + " age=" + age + " sex=" + sex)
}
//方法的调用从左到右赋值
// 指定参数名调用
function15(age = 15, name = "ysj", sex = "man")
函数定义注意点:
1)定义的方法 如果参数列表为空 那么在调用的时候可以加括号,也可以不加。
2)定义的方法 如果没有参数列表 那么在调用的时候不可以加括号。
3)没有返回值的方法 在参数列表括号后面直接添加方法体 我们称这种方法为过程。
//定义的方法 如果参数列表为空 那么在调用的时候可以加括号,也可以不加。
def function11() = {
"hello world!"
}
print(function11())
print(function11)
//定义的方法 如果没有参数列表 那么在调用的时候不可以加括号。
def function12 = {
println("function12")
}
// print(function12()) 编译错误
print(function12)
// 没有返回值的方法 在参数列表括号后面直接添加方法体 我们称这种方法为过程。
def function13(a: Int, b: Int) {
println(a + b)
}
函数的字面量(值函数)
在Scala语言中函数也是对象,也可以像变量一样被赋值,把这种函数称为函数字面量或者值函数。
1)通用定义格式: val 变量名=(参数列表)=>{函数体}
这里的变量名 即是方法名称也是方法返回值赋值给变量的变量名称。
val sum = (x: Int, y: Int) => {
print(x + y)
x + y
}
sum(2,5)
2)首先定义函数的参数列表类型,具体的函数参数在函数体中定义
/*首先定义函数的参数列表类型,具体的函数参数在函数体中定义*/
val sum2:(Int,Int,Int)=> Int={
(x,y,z)=>{
x+y+z
}
}
sum2(1,2,3)
高阶函数
值函数的作用主要作为高阶函数的输入
常用的高阶函数 map 、flatMap、filter、reduce、fold
/*值函数的使用场景就是作为高阶函数的输入*/
val arrInt=Array(1,2,3,4)
val increment=(x:Int)=>x+1
arrInt.map(increment)
/*实际应用中如果值函数只使用一次,常常直接作为函数参数*/
arrInt.map((x:Int)=>x+1)
//map的函数输入类型可以自动类型推断推断出来 可以省略
arrInt.map((x)=>x+1)
//map中的值函数(x)=>x+1 参数只有一个的时候可以将值函数的输入参数的括号去掉
arrInt.map(x=>x+1)
//值函数x=>x+1 的输入参数在符号 =>右边只出现一次可以用占位符 _ 对该值函数进一步简化
arrInt.map(_+1)
/*1、 map的使用 def Map[B](f:(A)=>B):Array[B]
* 将函数f作用于数组的所有元素,并返回一个新的数组 Array[B] f函数的输入类型为A 输出类型为B*/
val arrString = Array("hive", "spark", "hadoop")
arrString.map(_ * 2)
// Array(hivehive, sparkspark, hadoophadoop)
val arrInt = Array(1, 2, 3)
arrInt.map(_ * 2) //Array(2, 4, 6)
/*集合类型的map函数使用*/
val listString=List("hive"->1,"spark"->2,"hadoop"->3)
listString.map(x =>x._1)
/*简化*/
listString.map(_._1)
/*Map类型的 map函数的使用*/
val mapString=Map("hive"->1,"spark"->2,"hadoop"->3)
mapString.map(x=>x._1)
/*2、flatMap函数的使用
* 将函数f作用于集合中所有的元素,各元素得到相应的集合 ,然后再将其扁平化返回 */
val listInt=List(1,2,3)
listInt.flatMap(x => x match {
case 1 => List(1)
case _=>List(x)
}) //List(1, 2, 3)
listInt.map(x => x match {
case 1 => List(1)
case _=>List(x*2)
})//List(List(1), List(4), List(6))
/*map和flatMap的区别就是 map是来几条数据出几条数据 flatMap是多条数据输入 输出一条*/
/*reduce 数据的聚合 x+y的值作为下次的x */
val arrReduce=Array(1,2,3)
arrReduce.reduce((x:Int,y:Int)=>{println(x,y);x+y})
arrReduce.reduce(_+_)
/*filter函数的使用*/
arrReduce.filter(x=>x>2)
arrReduce.filter(_>2)
/*fold函数
* 使用联合二元算子对集合进行fold操作*/
arrReduce.fold(0)((x: Int, y: Int) => {
println(x, y);
x + y
})
/*(0,1)
(1,2)
(3,3)
res16: Int = 6*/
}
闭包
/*闭包
*代码val f=(x:Int) =>x +i 定义了一个函数字面量,函数中使用自由变量i,
* 变量i在程序的运行中会发生变化,处于开放的状态
* 而当函数执行的时候,自由变量已经被确定下来,
* 此时认为在运行的时候它暂时处于封闭的状态,
* 这样由开放到封闭过程的函数称为闭包 */
var i = 15
val f = (x: Int) => x + i
f(10) //25
i = 25
f(10) //35
函数柯里化
def 函数名称(参数列表)(参数列表):返回值类型={函数体}
def multiply(a: Int)(b: Int) = {
a + b
}
println(multiply(2)(4))
部分应用函数
上面的柯里化函数其实是两个函数组成的一个函数。
multiply(10) 函数返回的其实是第二个函数。可以使用 下划线 "_"将返回的函数转为部分应用函数。
scala> val pal=multiply(10)_
pal: Int => Int = <function1>
//调用部分应用函数 fal
scala> pal(50)
res13: Int = 60
两个参数都不指定的部分应用函数
scala> val pal2= multiply_
scala> pal2(10)(12)
res18: Int = 22
不只是柯里化函数有部分应用函数,普通的函数也有部分应用函数
//普通函数
scala> def product(x1:Int,x2:Int,x3:Int) = x1* x2 *x3
product: (x1: Int, x2: Int, x3: Int)Int
//一个参数的部分应用函数 product_1
scala> def product_1=product(_:Int,2,3)
product_1: Int => Int
//调用部分应用函数
scala> product_1(1)
res22: Int = 6
//两个参数的部分应用函数 product_2
scala> def product_2=product(_:Int,_:Int,3)
product_2: (Int, Int) => Int
//调用部分应用函数
scala> product_2(2,3)
res0: Int = 18
//三个参数的部分应用函数 product_3
scala> def product_3=product(_:Int,_:Int,_:Int)
product_3: (Int, Int, Int) => Int
//调用部分应用函数
scala> product_3(10,20,30)
res2: Int = 6000
//三个参数的部分应用函数 等价于product(_:Int,_:Int,_:Int)
scala> def product_3=product _
product_3: (Int, Int, Int) => Int
//调用部分应用函数
scala> product_3(10,20,30)
res3: Int = 6000