Scala中函数可以不依赖于类、对象、接口单独存在,函数可以作为函数的参数、返回值。
scala> def fun1(name:String){println(name)} //定义函数
fun1: (name: String)Unit
scala> val fun1_v = fun1 _ //将函数赋值给fun1_v
fun1_v: String => Unit = <function1>
scala> val fun1_v = fun1 _
fun1_v: String => Unit = <function1>
scala> fun1("spark")
spark
scala> fun1_v("spark")
spark
匿名函数:为了使用简洁,将函数直接赋值给变量,使用函数时通过调用变量实现,称为匿名函数。
scala> val fun2 = (content:String) => println(content) //定义匿名函数
fun2: String => Unit =
scala> fun2("Spark")
Spark
高阶函数:即某个函数的参数或返回值也是函数。
scala> val hiScala = (content:String) => println(content) //定义匿名函数
hiScala: String => Unit =
scala> def bigData(func:(String) => Unit, content:String){func(content)} //定义高阶函数
bigData: (func: String => Unit, content: String)Unit
scala> bigData(hiScala, "Spark")
Spark
scala> val array = Array(1,2,3,4,5,6,7,8,9)
array: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> array.map(item => item * 2) //map内参数为匿名函数
res5: Array[Int] = Array(2, 4, 6, 8, 10, 12, 14, 16, 18)
//返回值为函数举例
scala> def func_Returned(content:String) = (message:String) => println(content + " " + message)
func_Returned: (content: String)String => Unit
scala> val returned = func_Returned("Spark")
returned: String => Unit =
scala> returned("Scala")
Spark Scala
如果在函数的函数体中,某个输入参数的值只使用了一次,此时可以将参数名称省略,用下划线“_”表示。
scala> def spark(func:(String) => Unit, name:String){func(name)}
spark: (func: String => Unit, name: String)Unit
scala> spark((name:String) => println(name), "Scala")
Scala
scala> spark(name => println(name), "Scala") //类型推断
Scala
scala> spark(println(_), "Scala") //进一步简化
Scala
scala> spark(println, "Scala") //只有一个参数,直接省略
Scala
scala> val array = Array(1,2,3,4,5,6,7,8,9)
array: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> array.map(_*2).filter(_ > 10).foreach(println)
12
14
16
18
闭包:函数的变量超出其有效作用域时,仍然可以对函数内部变量进行访问。
scala> def scala(content:String) = (message:String) => println(content + " " + message)
scala: (content: String)String => Unit
scala> val funcResult = scala("Spark") //执行完毕后content的内容仍然可以被访问
funcResult: String => Unit =
scala> funcResult("Flink") //此时变量content的值Spark超出了函数scala的作用域,但依旧可以成功访问,即为闭包
Spark Flink
闭包内部实现原理:Scala内部自动生成了一个函数对象,把变量作为该对象的成员,而函数本身也是对象的成员,执行函数后,函数的返回结果也是该对象的成员,自然可以进行变量的调用。
函数柯里化:是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。柯里化本身也用到了闭包。
//未柯里化
scala> def sum(x:Int, y:Int) = x + y
sum: (x: Int, y: Int)Int
scala> sum(1, 2)
res14: Int = 3
//柯里化
scala> def sum_Currying(x:Int) = (y:Int) => x + y
sum_Currying: (x: Int)Int => Int
scala> sum_Currying(1)(2)
res19: Int = 3
//代码简化
scala> def sum_Currying_better(x:Int)(y:Int) = x + y
sum_Currying_better: (x: Int)(y: Int)Int
scala> sum_Currying_better(1)(2)
res21: Int = 3
将两个参数的函数变成了两个函数的连续调用。
scala> (1 to 100).reduceLeft(_+_) //1+2=3,3+3=6...
res22: Int = 5050
集合的高阶函数操作:
scala> val list = List("scala", "spark")
list: List[String] = List(scala, spark)
scala> val cal = list.map("The content is: " + _)
cal: List[String] = List(The content is: scala, The content is: spark)
scala> cal.flatMap(_.split(" "))
res25: List[String] = List(The, content, is:, scala, The, content, is:, spark)
scala> list.zip(List(1,2))
res26: List[(String, Int)] = List((scala,1), (spark,2))