Scala函数的定义,使用以及练习

it2023-06-24  70

Scala方法与函数

一.方法1.方法声明2.方法定义3.方法调用 二.java Lambda表达式三.Scala方法和函数1.函数定义2.函数调用(1)传值调用(call-by-value)(2)传名调用(call-by-name) 3.命名函数4.参数缺省值(即默认值)5.匿名函数6.高阶函数(1) 函数作为参数(2)函数作为返回值 7.中置表达式8.函数嵌套9.柯里化(Currying)10.隐式函数11.隐式函数12.闭包 四.作业练习1.函数定义2.匿名函数3.高阶函数4.嵌套函数

Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量。换句话来说在类中定义的函数即是方法。

Scala 中的函数则是一个完整的对象,Scala 中的函数其实就是继承了 Trait 的类的对象。

Scala 中使用 val 语句可以定义函数,def 语句定义方法

一.方法

1.方法声明

如果你不写等于号和方法主体,那么方法会被隐式声明为抽象(abstract),包含它的类型于是也是一个抽象类型

def functionName ([参数列表]):[return type]

2.方法定义

def functionName([参数列表]):[return type]={ function body return [expr] }

示例

//有返回值 def add(a:Int,b:Int):Int={ var sum:Int=0 sum=a+b return sum } //无返回值 def printMe( ) : Unit = { println("Hello, Scala!") }

3.方法调用

functionName(参数列表) //如果方法使用了实例的对象来调用,我们可以使用类似java的格式 (使用 . 号): [instance.]functionName( 参数列表 )

二.java Lambda表达式

函数式接口

一种只含有一个抽象方法声明的接口可以使用匿名内部类类实例化函数式接口的对象通过lambda表达式可以进一步简化代码

lambda语法

(parameters)->expression (parameters)_>{statements;...}

内置四大函数式接口

消费接口: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方法和函数

1.函数定义

函数式编程:函数是Scala的核心方法是类的一部分,属于定义在类中的函数函数定义: //定义函数方式一 def 函数名([参数列表])[:返回类型]={ //返回类型为Unit的函数,称为过程(可省略=) 函数体 [return] 表达式 } //匿名函数定义 (参数列表)=>{函数体} val f1=(x:Int,y:Int)=>x+y 123456

2.函数调用

函数调用:函数名(参数列表)

(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) //调用时不计算

3.命名函数

通常情况下,传入参数与函数定义的参数列表一一对应命名参数允许使用任意顺序传入参数 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") //任意顺序

4.参数缺省值(即默认值)

Scala函数允许指定参数的缺省值,从而允许在调用函数时不指明该参数 def printName(first:String="John", last:String="Smith") = { println(first + " " + last) } //Prints "John Smith" printName() printName("zhang") printName("zhang","san") //输出 John Smith zhang Smith zhang san

5.匿名函数

(参数列表)=>{函数体}

指不含函数名称的函数匿名函数定义 “=>”左边为参数列表 “=>”右边为函数体 如果函数体包括多条语句,应使用“{}”包含 val f1=(x:Int)=>{println(x);x*x}//将匿名函数赋值给变量f1 println(f1(2)) //输出 2 4

6.高阶函数

高阶函数可以将其他函数作为参数或者使用函数作为输出结果 常用高阶函数 map foreach filter fold、foldLeft、foldRight reduce zip flatten flatMap

(1) 函数作为参数

//定义一个普通函数 def square(x:Int)=x*x val f0=(x:Int)=>x*x //定义一个高阶函数 def dosquare(f:Int=>Int,p:Int):Int=f(p) println(dosquare(square,2)) println(dosquare(f0, 8)) //输出 4 64

(2)函数作为返回值

//将函数作为返回值 def dosquare2()={(x:Int)=>x*x} //调用函数 println(dosquare2()(2)) //输出 4 常用高阶函数 map:集合里的所有元素都进行一样的操作 foreach:进行打印遍历 filter:过滤 fold、foldLeft、foldRight:折叠计算 reduce:归约操作 zip:拉链 flatten:扁平化处理 flatMap:先flatten再Map //定义集合List为l scala> val l=List(1,2,3,4,5,6,7,8,9) l: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9) //map scala> l.map(x=>x*2) res1: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18) scala> l.map(_*2) res5: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18) //foreach注意println不能有括号,有括号的话会默认返回Unit值 scala> l.foreach(println) 1 2 3 4 5 6 7 8 9 //map和foreach结合使用 scala> l.map(x=>x*2).foreach(println) 2 4 6 8 10 12 14 16 18 //filter scala> l.filter(x=>(x>8)) res4: List[Int] = List(9) scala> l.filter(_>8) res6: List[Int] = List(9) //fold:集合l中元素进行相加操作,初始值为0 scala> l.fold(0)((sum,i)=>sum+i) res8: Int = 45 scala> l.fold(0)((sum,i)=>{println(sum,i);sum+i}) (0,1) (1,2) (3,3) (6,4) (10,5) (15,6) (21,7) (28,8) (36,9) res9: Int = 45 //foldLeft scala> l.foldLeft(0)((sum,i)=>{println(sum,i);sum+i}) (0,1) (1,2) (3,3) (6,4) (10,5) (15,6) (21,7) (28,8) (36,9) res10: Int = 45 //foldRight scala> l.foldRight(0)((sum,i)=>{println(sum,i);sum+i}) (9,0) (8,9) (7,17) (6,24) (5,30) (4,35) (3,39) (2,42) (1,44) res11: Int = 45 scala> l.foldRight(0)((sum,i)=>{println(sum,i);sum*i}) (9,0) (8,0) (7,0) (6,0) (5,0) (4,0) (3,0) (2,0) (1,0) res12: Int = 0 scala> l.foldRight(1)((sum,i)=>{println(sum,i);sum*i}) (9,1) (8,9) (7,72) (6,504) (5,3024) (4,15120) (3,60480) (2,181440) (1,362880) res13: Int = 362880 //reduce scala> l.reduce(_+_) res14: Int = 45 scala> l.reduce((x,y)=>x+y) res16: Int = 45 scala> l.reduce((x,y)=>x*y) res17: Int = 362880 scala> val list1=List(1,2,3,4) list1: List[Int] = List(1, 2, 3, 4) scala> val list2=List("a","b","c","d") list2: List[String] = List(a, b, c, d) //zip生产新的List,list里面为元组 scala> list1.zip(list2) res18: List[(Int, String)] = List((1,a), (2,b), (3,c), (4,d)) scala> val list3=list1.zip(list2) list3: List[(Int, String)] = List((1,a), (2,b), (3,c), (4,d)) scala> val list5=List(List(1,2),List(3,4),List(5,6)) list5: List[List[Int]] = List(List(1, 2), List(3, 4), List(5, 6)) //flatten中List里面也需要是List,平摊开 scala> list5.flatten res20: List[Int] = List(1, 2, 3, 4, 5, 6) scala> list5.flatten.map(_*2) res21: List[Int] = List(2, 4, 6, 8, 10, 12) //flatMap scala> list5.flatMap(_.map(_*2)) res22: List[Int] = List(2, 4, 6, 8, 10, 12)

使用高阶函数实现wordcount

//定义一个list scala> val list6=List("hadoop spark","hello world","hello java") list6: List[String] = List(hadoop spark, hello world, hello java) //1.将list6进行空格切割 scala> list6.map(_.split(" ")) res25: List[Array[String]] = List(Array(hadoop, spark), Array(hello, world), Array(hello, java)) //2.切割后进行平摊 scala> list6.map(_.split(" ")).flatten res27: List[String] = List(hadoop, spark, hello, world, hello, java) //上面两步的合并操作 scala> list6.flatMap(_.split(" ")) res28: List[String] = List(hadoop, spark, hello, world, hello, java) //3.将没个单词转成元组,方便后面进统计(hadoop,1) scala> list6.flatMap(_.split(" ")).map(x=>(x,1)) res29: List[(String, Int)] = List((hadoop,1), (spark,1), (hello,1), (world,1), (hello,1), (java,1)) //4.通过对单词进行分组,即根据元组的第一个元素进行分组 scala> list6.flatMap(_.split(" ")).map(x=>(x,1)).groupBy(x=>x._1) res30: scala.collection.immutable.Map[String,List[(String, Int)]] = Map(world -> List((world,1)), java -> List((java,1)), hadoop -> List((hadoop,1)), spark -> List((spark,1)), hello -> List((hello,1), (hello,1))) //5.通过对组内元素进行统计得出数量 scala> list6.flatMap(_.split(" ")).map(x=>(x,1)).groupBy(x=>x._1).map(x=>(x._1,x._2.size)) res32: scala.collection.immutable.Map[String,Int] = Map(world -> 1, java -> 1, hadoop -> 1, spark -> 1, hello -> 2) //6.遍历打印出来 scala> list6.flatMap(_.split(" ")).map(x=>(x,1)).groupBy(x=>x._1).map(x=>(x._1,x._2.size)).foreach(println) (world,1) (java,1) (hadoop,1) (spark,1) (hello,2) //7.进行简化打印出来 scala> list6.flatMap(_.split(" ")).map((_,1)).groupBy(_._1).map(x=>(x._1,x._2.size)).foreach(println) (world,1) (java,1) (hadoop,1) (spark,1) (hello,2) //扩展:进行安装次数排序 scala> list7.map(_.split(" ")).flatten.map(x=>(x,1)).groupBy(x=>x._1).map(x=>(x._1,x._2.size)).toList res62: List[(String, Int)] = List((are,1), (am,3), (oldhu,1), (i,3), (you,1), (who,1), (ok,1), (fine,1)) //将元组的元素进行调换 scala> list7.map(_.split(" ")).flatten.map(x=>(x,1)).groupBy(x=>x._1).map(x=>(x._1,x._2.size)).toList.map(x=>(x._2,x._1) ) res65: List[(Int, String)] = List((1,are), (3,am), (1,oldhu), (3,i), (1,you), (1,who), (1,ok), (1,fine)) //降序排序 scala> list7.map(_.split(" ")).flatten.map(x=>(x,1)).groupBy(x=>x._1).map(x=>(x._1,x._2.size)).toList.map(x=>(x._2,x._1)).sortBy(x=>x._1*(-1)) res66: List[(Int, String)] = List((3,am), (3,i), (1,are), (1,oldhu), (1,you), (1,who), (1,ok), (1,fine)) //打印出来 scala> list7.map(_.split(" ")).flatten.map(x=>(x,1)).groupBy(x=>x._1).map(x=>(x._1,x._2.size)).toList.map(x=>(x._2,x._1)).sortBy(x=>x._1*(-1)).foreach(println) (3,am) (3,i) (1,are) (1,oldhu) (1,you) (1,who) (1,ok) (1,fine)

7.中置表达式

中置(缀)表达式是对只有一个参数的方法调用约定 当方法只有一个参数时,可以省略“.”和“()” //省略了括号和. scala> 1 to 10 res71: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) scala> 1.to(10) res72: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) // scala> List(1,2,3).map(x=>x+1).foreach(println) 2 3 4 //使用中置表达式 scala> val f=(x:Int)=>x+1 f: Int => Int = <function1> scala> List(1,2,3) map f foreach println 2 3 4

8.函数嵌套

Scala函数内可以定义函数,函数内的函数也称局部函数或者内嵌函数

//进行阶乘计算 //调用函数 println(factorial(4)) //定义一个外层函数 def factorial(i:Int):Int={ //定义一个嵌套函数 def fact(i:Int,acc:Int):Int={ if(i<=1){ acc }else{ fact(i-1,i*acc) } } fact(i,acc=1) } //输出 24

9.柯里化(Currying)

方法可以定义多个参数列表,当使用较少的参数列表调用多参数列表的方法时,会产生一个新的函数,该函数接收剩余的参数列表作为其参数。这被称为柯里化

fold(0)()就是柯里化使用

//单参数列表 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)(_)

10.隐式函数

方法可以具有隐式参数列表,由参数列表开头的implicit 关键字标记 implict只能修改最尾部的参数列表,应用于其全部参数 Scala可自动传递正确类型的隐式值 通常与柯里化函数结合使用 def sum(x:Int)(implicit y:Int)=x+y implicit var a=10 //将作为Int类型隐式值自动传递 println(sum(56)) //输出 66

11.隐式函数

隐式函数也称隐式转换,使用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) //输出 2

12.闭包

闭包是依照包含自由变量的函数字面量在运行时创建的函数值闭包是对函数本身及其所使用的自由变量的统一定义 //自由变量可变 var y=1 def add(x:Int)=x+y //add是闭包,y是自由变量 println(add(10)) y=20 println(add(10)) //输出 11 20 闭包的变量绑定 闭包可捕获自由变量的变化 闭包对捕获变量作出的改变在闭包之外也可见

四.作业练习

1.函数定义

需求说明 定义一个没有返回值的函数,实现输入一个整数,打印金字塔。例如输入5,打印如下:

object test02 { def main(args: Array[String]): Unit = { print1(5) } def print1(x:Int)={ for(i <-1 to x){//行数 for (j<- 0 to x-i){ print(" ") } for(j <-1 to 2*i-1){ print("*") } println() } } }

2.匿名函数

需求说明 定义一个去除字符串首尾空格的函数字面量trim 定义一个截取字符串首字母的函数字面量initial

def main(args: Array[String]): Unit = { println(f1(" dfsdf ")) println(f2("tdasdfsad")) } val f1=(x:String)=>x.trim; val f2=(y:String)=>y.substring(0,1)//包括索引0,不包括1

3.高阶函数

编写函数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()函数实现上述逻辑

import scala.collection.mutable.ListBuffer object test02 { def main(args: Array[String]): Unit = { println(values(x=>x*x, -5, 5)) } def fun(x:Int,y:Int)=x*x def values(fun:Int=>Int,low:Int,hight:Int): ListBuffer[(Int,Int)]={ var list=new ListBuffer[(Int,Int)] for (i <-low to hight) list.append((i,fun(i))) list } } //输出 ListBuffer((-5,25), (-4,16), (-3,9), (-2,4), (-1,1), (0,0), (1,1), (2,4), (3,9), (4,16), (5,25))

4.嵌套函数

需求说明 编写Scala函数实现斐波纳契数列

输出 1、1、2、3、5、8、13、21、……

object test02 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+" ")) }
最新回复(0)