配色: 字号:
Scala函数式编程彻底精通
2016-11-07 | 阅:  转:  |  分享 
  
Scala函数式编程彻底精通

简介:

本篇博文主要是对Scala函数式编程的彻底详解,涉及高阶函数,闭包,颗粒化等详解。

1.Scala函数式编程

Scala中的函数的可以不依赖类或则借口,独立存在,甚至函数可以作为参数传递,可以直接赋值给变量。

Scala的函数式编程使得算法的设计可以更高效更精简,因为函数式是依赖人们的思考方式构建的。

Scala的函数式编程是的开发代码行数更少。

Spark中的计算几乎所有都是用函数式编写的,而且我们在处理数据一般都是针对集合的,集合的函数式编程更是重中之重,以及基于scala的函数式操作集合。

高阶函数:

如果一个函数是一个函数的参数则称为此函数为高阶函数

高阶函数是scala与Java的最大不同。



scala>deffun1(name:String){println(name)}

//fun1为函数的名称,(name:String)参数Unit是返回值为Unit

//为啥返回的值是Unit,因为println不会直接参数结果,他只会具体完成工作。

fun1:(name:String)Unit



//现在将函数赋值给变量

//valfun1_v=fun1_//函数名_中间一定要加空格

//这时候的fun1_v就是函数了

scala>valfun1_v=fun1_//fun1_此时就表示函数本身了

//此时我们看出fun1_v就是函数了,参数的类型是String类型,返回值是Unit

//=>是将左边的参数进行右边的加工。

fun1_v:String=>Unit=

scala>fun1("Spark")

Spark



scala>fun1_v("Spark")

Spark



scala>fun1_v("Scala")

Scala

匿名函数

在实际工作的时候,比如算法设计我们可能不需要函数名称,只需要函数执行的功能就可以了,这时候我们就会使用匿名函数。

但是我们要使用它,就可以借助函数赋值给变量,变量就变成了函数的性质,将匿名函数赋值给变量。

匿名函数的定义规则:

(参数:类型)=>函数的操作



scala>valfun2=(content:String)=>println(content)

fun2:String=>Unit=



scala>fun2("Hadoop")

Hadoop

高阶函数

函数的参数也是函数,为啥可以?因为前面谈到了函数可以赋值给变量,而我们现在直接把函数作为函数的参数,也应该是可以的。

这样的设计非常强大:

例如:我们使用函数去操作集合,可能需要循环遍历集合,这个时候我们就可以使用函数参数,而此时的函数参数具有遍历集合的功能。



//第一个参数,定义了一个函数,func是函数的名称,(String)是变量的类型,=>Unit指定函数的返回值是Unit

//第一个传入参数的要求是:定义一个函数,函数值是Unit

scala>valhiScala=(content:String)=>println(content)

hiScala:String=>Unit=



scala>defbigData(func:(String)=>Unit,content:String){func(content)}

bigData:(func:String=>Unit,content:String)Unit



//传入的第一个参数是一个函数,传入第二个参数的时候,content就会作为参数传入//第一个hiScala函数里面

scala>bigData(hiScala,"Spark")

Spark



//item=>(2item)是一个匿名函数,作为参数传入到map()函数中,map函数的作用是循环遍历集合中的所有元素。

scala>array.map(item=>(2item))

res5:Array[Int]=Array(2,4,6,8,10,12,14,16,18)

另外,高阶函数的返回值也有可能是函数



scala>deffunc_Returned(content:String)=(message:String)=>println(message)

//匿名函数本身是返回值,所有返回类型是Unit,func_returned()函数的返回值类型//是String.

func_Returned:(content:String)String=>Unit



scala>func_Returned("Spark")

//执行结果是一个函数

//输入类型是字符串String,为啥呢?因为(message:String)输入参数是String,返回类//型是Unit,因为println(message)是一条打印语句。

res7:String=>Unit=



scala>deffunc_Returned(content:String)=(message:String)=>println(content+""+message)

func_Returned:(content:String)String=>Unit



scala>valreturned=func_Returned("Spark")

returned:String=>Unit=



//为啥会打印Spark此时的Spark是上面deffunc_Returned(content:String)=//(message:String)=>println(content+""+message)为参数的输入值

//为啥会打印Scala因为returned=func_Returned("Spark"),是把函数的返回值为函数//的返回值赋值给了returned,也就相当于把(message:String)=>println(content+""+//message)赋值给了returned,此时我们传入参数,也就是message的参数,content//之前传过了。



scala>returned("Scala")

SparkScala

高阶函数的两个层面:

1.函数的参数是函数

2.函数的返回值是函数

高阶函数有一个重要的性质就是类型推断,可以自动推断出具体的参数和类型,并且对于只有一个参数的函数,可以省略掉小括号,如果在参数作用的函数体内,只使用一次输入参数的参数值的话,那么可以将函数的输入参数的名称省略,用下划线_来代替。



//之前定义函数的时候是func:(content:String),因为函数中就一个参数,就可以将函数的参数名省略。

scala>defspark(func:(String)=>Unit,name:String){func(name)}

spark:(func:String=>Unit,name:String)Unit



scala>spark((name:String)=>println(name),"Scala")

Scala

//为啥可以省略掉String,因为我们定义的时候传入的参数是String类型,而且确实传入的值也是String类型,scala可以进行类型推导,所以可以省略。

scala>spark((name)=>println(name),"Scala")

Scala



//如果只有一个参数的时候()也可以省略掉了。

scala>spark(name=>println(name),"Scala")

Scala



//因为函数体本身只有一个参数,所以可以将参数省略掉,用下划线代替。

scala>spark(println(_),"Scala")

Scala



//如果只有一个参数的时候,()也可以省略。

scala>spark(println,"Scala")

Scala

scala>valarray=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=>(2item))

res5:Array[Int]=Array(2,4,6,8,10,12,14,16,18)

//因为只有一个参数所以可以省略参数名,直接用下划线代替。

scala>array.map(2_)

res13:Array[Int]=Array(2,4,6,8,10,12,14,16,18)



//此时filter是高阶函数

scala>array.map(2_).filter(_>10).foreach(println)



//(_+_)里面就是一个函数,第一个_的值是前n次求和的结果,第二个_是第n+1项的结果。

scala>(1to100).reduceLeft(_+_)

res19:Int=5050

闭包:

函数的变量,超出他的有效作用域中我们还能对函数的内部变量进行访问。



scala>defscala(content:String)=(message:String)=>println(content+":"+message)

scala:(content:String)String=>Unit



//通用的角度来看,scala函数执行之后,spark是不会存在的。因为content是scala的局部//变量。在函数执行完之后是不会存在的。

scala>valfuncResult=scala("Spark")

funcResult:String=>Unit=





//这里为啥还可以打印出来Spark

//而scala执行完之后,里面的成员依旧可以被访问这就是闭包。

//也就是说content的内容被保存在函数体内部可以被反复的使用。

//闭包的实现原理是:Scala为我们当前的函数生成了一个当前我们看不到的对象,把我们对象的content成员,而scala函数也是对象的成员,当我们执行scala函数的时候,也就是执行对象里面的函数,而对象里面的函数,访问函数里面的属性成员是非常正常的。



scala>funcResult("Flink")

Spark:Flink

颗粒化:

作用是将两个参数的函数,转换成两个函数,第一个函数的参数为两个参数函数的第一个参数,同理,第二个函数的参数为第二个参数。



scala>defsum(x:Int,y:Int)=x+y

sum:(x:Int,y:Int)Int



scala>sum(1,2)

res16:Int=3



scala>defsum_Currying(x:Int)=(y:Int)=>x+y

sum_Currying:(x:Int)Int=>Int



scala>sum_Currying(1)(2)

res17:Int=3



scala>defsum_Currying_Better(x:Int)(y:Int)=x+y

sum_Currying_Better:(x:Int)(y:Int)Int



scala>sum_Currying_Better(1)(2)

res18:Int=3

集合:



//创建一个集合

scala>vallist=List("Scala","Spark","Fink")

list:List[String]=List(Scala,Spark,Fink)



//map函数会遍历整个集合,"Thecontentis:"+_是一个函数,因为每个参数只用一次所以我们用下划线_代替。

scala>list.map("Thecontentis:"+_)

res20:List[String]=List(Thecontentis:Scala,Thecontentis:Spark,Thecontentis:Fink)



scala>valcal=list.map("Thecontentis:"+_)

cal:List[String]=List(Thecontentis:Scala,Thecontentis:Spark,Thecontentis:Fink)



scala>cal

res21:List[String]=List(Thecontentis:Scala,Thecontentis:Spark,Thecontentis:Fink)



scala>cal.flatMap(_.split(""))

res22:List[String]=List(The,content,is,:,Scala,The,content,is,:,Spark,The,content,is,:,Fink)



scala>cal.flatMap(_.split("")).foreach(print)

Thecontentis:ScalaThecontentis:SparkThecontentis:Fink

scala>list.zipwww.wang027.com(List(10,6,5))

res24:List[(String,Int)]=List((Scala,10),(Spark,6),(Fink,5))

统计一个文件夹下面的所有的单词出现的总次数

1.文件个数

2.文件里面的文件怎么统计



packageThirdWordCount



objectWordCounter{

//导入jar包

importscala.io.Source

importjava.io._

//存储单词和个数

varmap=Map.empty[String,Int]



defmain(args:Array[String]):Unit={

scanDir(newFile("E://aa"))

map.foreach(f=>

println(f)

)

}



defscanDir(dir:File):Unit={

dir.listFiles.foreach{file=>

if(file.isFile()){

readFile(file)

println(file)

}

}

}



defreadFile(file:File){

valf=Source.fromFile(file)

for(line<-f.getLines()){

count(line)

}

}

献花(0)
+1
(本文系thedust79首藏)