Scala函数
Java Lambda
函数式接口:
- 一种只含有一个抽象方法声明的接口
- 可以使用匿名内部类实例化函数式接口的对象
- 通过Lambda表达式可以进一步简化代码
Lambda语法:
(parameters) -> expression
(parameters) -> { statements; }
Scala函数定义
def 函数名([参数列表]):[返回值]={
函数体
return [表达式]
}
实例:
def square(x:Int):Int={
println(x)
x * x
}
def sayHello(x:String):Unit={
println("Hello "+x)
}
函数调用
函数名(参数列表)
参数传递
传值调用 call-by-value
传值调用时,参数只在调用时计算一次,后续重复使用计算结果
def square(x:Int):Int={
println(x) //3
x * x
}
square(1+2) // 先计算1+2
传名调用 call-by-name
传名调用时,参数在调用时不会计算,只有真正用到参数时才计算
def square(x:=>Int):Int={
println(x) //计算1+2
x * x //计算(1+2)*(1+2)
}
square(1+2) //不计算
命名参数
通常情况下,传入参数与函数定义的参数列表一一对应,而命名参数允许使用任意顺序传入参数
def showMsg(name:String,age:Int)={
println("Hello "+name+" age:"+age)
}
showMsg("kb09",3)
showMsg(age=18,name="zhangsan")
参数缺省值
Scala函数允许指定参数的缺省值,从而允许在调用函数时不指明该参数
def printName(first:String="John",last:String="Smith")={
println(first+" "+last)
}
printName() //输出"John Smith"
参数个数未知
def showMsg2(name:String,str:String*)={
println(name)
for (s<-str){
print(s+"\t")
}
}
showMsg2("kb09","zhangsan","lisi","wangwu")
匿名函数
匿名函数指不含函数名称的函数
匿名函数的定义:
(参数列表)=>{函数体}
//如果函数体包含多条语句,应使用{}包含
匿名函数调用实例:
(a:Int, b:Int)=>a+b
//用变量去接受匿名函数
val aa=(a:Int, b:Int)=>a+b
val bb=aa
println(aa(1,3)) //输出4
println(bb(3,5)) //输出8
函数作参数
def fun(a:Int,b:Int)=a+b
def fun1(a:Int,b:Int)=a-b
def fun2(a:Int,b:Int)=a*b
def funTest(f:(Int,Int)=>Int,s:String)={
val resValue = f(10,20)
s+resValue
}
println(funTest(fun, "SUM:")) //30
println(funTest(fun1, "DIFF:")) //-10
println(funTest(fun2, "MULTI:")) //200
println(funTest((a:Int,b:Int)=>a*2+b*3, "SELFMADE:")) //80
函数作返回值
def funTest2():(String,String)=>String={
def fun3(str1:String, str2:String):String={
str1+"||"+str2
}
fun3
}
var strValue=funTest2()("aa","bb")
println(strValue) //输出"aa||bb"
课堂小测
输出一个指定数的阶乘(递归思路)
def jc(a:Int)={
if (a==1) 1
else a*jc(a-1)
}
println(jc(8)) //40320
柯里化Currying
方法可以定义多个参数列表,当使用较少的参数列表调用多参数列表的方法时,会产生一个新的函数,该函数接收剩余的参数列表作为其参数。这被称为柯里化
//单参数列表
def modN(n: Int,x: Int) = ((x % n) == 0)
//多参数列表
def modN(n: Int)(x: Int) = ((x % n) == 0)
//新函数接收剩余的参数列表作为其参数
def f1(x: Int) = modN(10)(x)
def f2(n: Int) = modN(n)(10)
def f3 = modN(10)(_)
def fun(a:Int,b:Int,c:Int,d:Int)=a+b+c+d
def fun1(a:Int,b:Int)(c:Int,d:Int)=a+b+c+d
def fun2(a:Int)(b:Int)(c:Int)(d:Int)=a+b+c+d
println(fun2(1)(2)(3)(4))
隐式参数
方法可以具有隐式参数列表,由参数列表开头的implicit关键字标记
- implict只能修改最尾部的参数列表,应用于其全部参数
- Scala可自动传递正确类型的隐式值
- 通常与柯里化函数结合使用
//隐式参数
implicit var a:Int=10
implicit var str:String="hello"
def fun(a:Int,b:Int)(implicit c:Int):Int={
a+b+c
}
def fun1(a:Int,b:Int)(implicit c:Int=5,str:String):Int={
println(str)
a+b+c
}
//优先级:传参>隐式参数>默认
println(fun1(1, 2)(str="abc"))
隐式函数
隐式函数也称隐式转换,使用implicit修饰的函数
- 类型转换
implicit def double2Int(x:Double)=x.toInt
val i:Int=3.5
- 类型增强
implicit def bool2Int(x:Boolean)=if(x) 1 else 0
println(1+true)
更多隐式实例:
package Date1022
import Date1022.implicitpack._
class demo2{}
object demo2 {
def main(args: Array[String]): Unit = {
// val res1 = sum(10,10)
// println(res1)
// val res2 = showMsg("张三")
// println(res2)
// val res3:Int=3.5
// println(res3)
// val res4:Int="20"
// println(res4)
val dm =new demo2
println(dm.multi(4, 6))
println(dm.sum(10, 90))
println(dm.divide(30, 4))
}
def sum(a:Int,b:Int)(implicit c:Int):Int=a+b+c
def showMsg(name:String)(implicit s:String):String=s+name
//def multi(a:Int,b:Int)(implicit c:Int):Int=a*b*c
}
隐式类
package Date1022
class demo3{}
import Date1022.implicitpack._
object demo3 {
//隐式类的使用,与demo3相关的两个隐式类全部在Implicitpack中
//创建好demo3对象中,虽然demo3中没有一个方法,但是因为隐式
//类中是有好多方法的,因些demo3对象后就可以使用这些方法
//隐式类的主要作用就是类对象中没有的方法可以直接被类对象调用
def main(args: Array[String]): Unit = {
val dm3=new demo3
dm3.aa("k")
println(dm3.bb(19))
println(dm3.add(2, 5))
println(dm3.aa("zhangsan", "123"))
}
}
隐式包
package Date1022
object implicitpack {
implicit val a:Int=10
implicit val b:String="b"
implicit def doubletoint(value:Double): Int =value.toInt
implicit def stringtoint(value:String): Int =Integer.parseInt(value)
implicit class NumOperation(demo:demo2){
def multi(a:Int,b:Int)={
a*b
}
def sum(a:Int,b:Int)={
a+b
}
def sub(a:Int,b:Int)={
a-b
}
def divide(a:Int,b:Int)={
a/b
}
}
implicit class demo3_implicit(demo:demo3){
def aa(a:String): Unit ={
println(a+a)
}
def bb(num:Int): String ={
if (num%2==0) "偶数"
else "奇数"
}
def add(a:Int, b:Int): Int ={
a+b
}
}
implicit class demo3_implicit2(demo:demo3){
def aa(name:String,pwd:String):Boolean={
if (name=="张三" && pwd=="123456") true
else false
}
}
}
模式匹配
package Date1022
import java.io.FileNotFoundException
class Person
case class Teacher(name:String,subject:String) extends Person
case class Student(name:String,classroom:Int) extends Person
case class Worker(name:String,worktype:String) extends Person
case class Stranger() extends Person
object demo1 {
def matchMarks(name:String,marks:Int):Unit={
marks match {
case _ if marks >= 90 => println("High Distinction")
case _ if marks >= 80 => println("Distinction")
case _ if marks >= 70 => println("Good")
case _ if marks >= 60 => println("Normal")
case _a => println("Fail, score:" + _a)
//case _marks => println(s"$name's marks are "+_marks)
}
}
def matchException(e:Exception):Unit=e match {
case e:IndexOutOfBoundsException => println("下标越界")
case e:FileNotFoundException => println("找不到指定文件")
case e:NullPointerException => println("空指针异常")
case _:Exception => println("程序异常")
}
def matchArr(arr:Array[String]): Unit ={
arr match {
case Array("Jessica", _*) => println("Hello")
case Array(girl1, girl2, girl3) => println(girl1+" "+girl2+" "+girl3)
case _ => println("GoodBye")
}
}
def matchPerson(p:Person): Unit ={
p match {
case p:Teacher => println("你是"+p.name+"老师,你教"+p.subject)
case p:Student => println("你是"+p.name+"学生,你的教师在"+p.classroom)
case p:Worker if p.worktype=="修理工" => println("你是修理工")
case p:Stranger => println("我不认识你")
}
}
val map=Map("zs"->"a","ls"->"b","ww"->"c")
def matchMap(name:String):Unit={
var score=map.get(name)
score match{
case Some(score)=>println(name+"的成绩为"+score)
case None=>println(s"没有$name 的成绩")
}
}
def main(args: Array[String]): Unit = {
//matchMarks("zhangsan",57)
//matchException(new IndexOutOfBoundsException)
//val arr = Array("Jessica","Lily","Sofia","Lucy")
//matchArr(arr)
//val teacher = Teacher("张三","数学")
//matchPerson(teacher)
matchMap("zl")
}
}
部分函数
def showMess(title:String,content:String,num:Int):Unit={
println(title+" "+content+" "+num)
}
showMess("警告","",1)
val title="警告:"
def showWaterAlter =showMess(title,_:String,_:Int)
showWaterAlter("当前水位",12)
def add(a:Int,b:Int,c:Int)={
a+b+c
}
val a=5
def addadd=add(a,_:Int,_:Int)
println(addadd(4, 3))
偏函数
def funPartitional:PartialFunction[String,Int]={
case "hello" => 1
case "world" => 2
case _ => 0
}
println(funPartitional("world"))
val words=List("world","hello","gree","kb09")
words.collect(funPartitional).foreach(println)
words collect funPartitional foreach println
println(Array(1, 2) collectFirst {case x if x % 2 == 0 => x + 100})
def funTuple:PartialFunction[Char,(Char, Int)]={
case 'A'=>('A',1)
case 'B'=>('B',1)
case _=>('X',1)
}
val tuple:(Char,Int)=funTuple('A')
println(tuple)
var chars=List('A','B','C','D')
var tuples:List[(Char,Int)]=chars.collect(funTuple)
tuples.foreach(x=>println(x._1,x._2))
def fun2:PartialFunction[Any,Int]={
case i:Int=>i
case _=>0
}
var list=List('a','c',2,2.5,90)
list.collect(fun2).foreach(println)