一.Java Lambda表达式
函数式接口
- 一种只含有一个抽象方法声明的接口
- 可以使用匿名内部类来实例化函数式接口的对象
- 通过Lambda表达式可以进一步简化代码
Lambda语法
(parameters) -> expression
(parameters) ->{ statements;...... }
示例如下:
//Java8 方式
new Thread(() ->
System.out.println("In Java8,Lambda expression rocks !!"))
.start();
内置四大函数式接口
- 消费接口:Consumer
- 供给型接口:Supplier
- 断言型接口:Predicate
- 函数型接口:Function<T,R>
- 示例如下:
Consumer<String> consumer=(s)-> System.out.println(s.toUpperCase());
consumer.accept("testabc");
list.foreach(x-> System.out.println(x);)
Supplier <Double> supplier = () -> Math.random();
System.out.println(supplier.get());
Predicate<String> condition=s -> s.length()>4;
if(condition.test("hello")) System.out.println("true");
Function<String,String> toUpper=(s)->s.toUpperCase();
System.out.println(toUpper.apply("test"));
二.Scala方法和函数
- 函数式编程:函数是Scala的核心
- 方法是类的一部分,属于定义在类中的函数
- 函数定义:
def 函数名([参数列表])[:返回类型]={ //返回类型为Unit的函数,称为过程(可省略=)
函数体
[return] 表达式
}
//匿名函数定义
(参数列表)=>{函数体}
- 函数调用:函数名(参数列表)
- 1.传值调用(call-by-value):传值调用时,参数只在调用时计算一次,后续重复使用计算的结果
def square(x: Int): Int = {
println(x) //3
x * x //计算3*3
}
square(1+2) //先计算1+2
- 2.传名调用(call-by-name):传名调用时,参数在调用时不会计算,只有真正用到参数时才计算
def square(x: => Int): Int = {
println(x) //计算1+2
x * x //计算(1+2)*(1+2)
}
square(1+2) //调用时不计算
- 命名参数
- 通常情况下,传入参数与函数定义的参数列表一一对应
- 命名参数允许使用任意顺序传入参数
def printName(first:String, last:String) = {
println(first + " " + last)
}
//Prints "John Smith"
printName("John","Smith")
printName(first = "John",last = "Smith")
printName(last = "Smith",first = "John") //任意顺序
- 参数缺省值(即默认值)
- Scala函数允许指定参数的缺省值,从而允许在调用函数时不指明该参数
def printName(first:String="John", last:String="Smith") = {
println(first + " " + last)
}
//Prints "John Smith"
printName()
printName(“zhang”)
printName(“zhang”,”san”)
-
匿名函数
-
指不含函数名称的函数
-
匿名函数定义:“=>”左边为参数列表,“=>”右边为函数体,如果函数体包括多条语句,应使用“{}”包含
(x:Int)=>x*x
(x:Int)=>{println(x);x*x}
() => { System.getProperty("user.dir") }
val f1=(x:Int)=>{println(x);x*x} //将匿名函数赋值给变量f1
f1(2)
-
高阶函数
-
高阶函数可以将其他函数作为参数或者使用函数作为输出结果
-
常用高阶函数:map,foreach,filter,fold,reduce,zip,flatten,flatMap
//函数作为参数
def doSquare(f:Int=>Int,p:Int)=f(p)
def square(x:Int):Int=x*x
doSquare(square,square(2))
//函数作为返回值
//返回类型为函数(Int=>Int)
def doSquare()={
(x:Int)=>x*x
}
doSquare()(2)
- 中置表达式
- 中置(缀)表达式是对只有一个参数的方法调用约定,当方法只有一个参数时,可以省略“.”和“()”
//示例1
1 to 10
//实际调用
1.to(10)
//示例2
List(1,2,3).map(x=>x+1).foreach(println)
//使用中置表达式
val f=(x:Int)=>x+1
List(1,2,3) map f foreach println
- 函数嵌套
- Scala函数内可以定义函数,函数内的函数也称局部函数或者内嵌函数
//使用函数嵌套实现阶乘运算
def factorial(i: Int): Int = {
def fact(i: Int, accumulator: Int): Int = {
if (i <= 1)
accumulator
else
fact(i - 1, i * accumulator)
}
fact(i, 1) //不能在factorial()之外调用
}
-
柯里化(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)(_)
-
隐式参数
-
方法可以具有隐式参数列表,由参数列表开头的implicit 关键字标记
-
1)implict只能修改最尾部的参数列表,应用于其全部参数
-
2)Scala可自动传递正确类型的隐式值
-
3)通常与柯里化函数结合使用
def sum(x:Int)(implicit y:Int)=x+y
implicit var a=10 //将作为Int类型隐式值自动传递
sum(10) //20
-
隐式函数
-
隐式函数也称隐式转换,使用implicit修饰的函数
-
应用场景
-
1)类型转换
implicit def double2Int(x:Double)=x.toInt
val i:Int=3.5
- 2)类型增强
implicit def bool2Int(x:Boolean)=if(x) 1 else 0
println(1+true)
-
闭包
-
闭包是依照包含自由变量的函数字面量在运行时创建的函数值
-
闭包是对函数本身及其所使用的自由变量的统一定义
var y=1
val add=(x:Int)=>x+y //add是闭包,y是自由变量
- 闭包的变量绑定
- 1)闭包可捕获自由变量的变化
- 2)闭包对捕获变量作出的改变在闭包之外也可见
三.Scala函数练习
练习1:函数定义
package scala
/*需求说明
定义一个没有返回值的函数,实现输入一个整数,打印金字塔。例如输入10,打印如下:
读取一个整数:val x=StdIn.readInt()
*/
import scala.io.StdIn
object _0729pratice01 {
def jinzita()={
print("请输入一个整数:")
val x= StdIn.readInt()
for(i <- 1 to x){//行数
for(j <- x-i to 1 by -1 ) print(" ")
for(j <- 1 to 2*i-1) print("*")
println()
}
}
def main(args: Array[String]): Unit = {
jinzita()
}
}
练习2:匿名函数
package scala
/*需求说明
定义一个去除字符串首尾空格的函数字面量trim
定义一个截取字符串首字母的函数字面量initial
*/
object _0729pratice02 {
val f1 =(s:String)=>s.trim
val f2 = (s:String)=>s.substring(0,1)
def main(args: Array[String]): Unit = {
println(f1(" ss ")) //ss
println(f2("abcd"))//a
}
}
练习3:高阶函数
package scala
import scala.collection.mutable.ListBuffer
/*需求说明
编写函数values(fun:(Int)=>Int,low:Int,hight:Int)
该函数输出一个集合,对应给定区间内给定函数的输入和输出,比如values(x=>x*x,-5,5)将输出:
(-5,25)(-4,16)(-3,9)(-2,4)(-1,1)(0,0)(1,1)(2,4)(3,9)(4,16)(5,25)
使用map()函数实现上述逻辑
*/
object _0729practice03 {
def values(fun:(Int)=>Int,low:Int,high:Int):ListBuffer[(Int,Int)]={
var list = new ListBuffer[(Int,Int)]
for (i<- low to high) list.append((i,fun(i)))
list
}
def main(args: Array[String]): Unit = {
values(x=>x*x ,-5,5).foreach(print)
}
}
练习4:嵌套函数
package scala
/*需求说明
编写Scala函数实现斐波纳契数列
F(1)=1,F(2)=1
F(n)=F(n - 1)+F(n - 2)(n ≥ 3,n ∈ N*)
输出
1、1、2、3、5、8、13、21、……
*/
object _0729practice04 extends App {
//使用递归函数
def fun(x:Int)= {
def feibo(x:Int):Int=if (x==1||x==2) 1 else feibo(x-1)+feibo(x-2)
(1 to x).toArray.map(x=>feibo(x))
}
fun(10).foreach(x=>print(x+" "))
}