函数式编程:程序简单
//举例:实现WordCount
var result = sc.textFile("hdfs://******").flatMap(_.split("")).map((_,1)).reduceByKey(_+_).collect
1.Scala中的函数
在Scala中,函数是“头等公民”,就和数字一样。可以在变量中存放函数,即:将函数作为变量的值(值函数)。
object MyFun {
//定义函数
def myFun(name:String): String ={
"Hello"+name
}
def main(args: Array[String]): Unit = {
println(myFun(" plus"))
println("-----------------------")
//值函数,将函数作为变量的值
val a1 = myFun(" Tom")
println(myFun(a1))
}
}
2.匿名函数:没有名字的函数
scala> var myarray = Array(1,2,3)
myarray: Array[Int] = Array(1, 2, 3)
scala> def fun1(x:Int):Int = x * 3
fun1: (x: Int)Int
scala> (x:Int) = x * 3
<console>:1: error: ';' expected but '=' found.
(x:Int) = x * 3
^
匿名函数定义
scala> (x:Int) => x * 3
res0: Int => Int = <function1>
scala> fun1(2)
res1: Int = 6
调用匿名函数
scala> Array(1,2,3).map((x:Int) => x * 3)
res2: Array[Int] = Array(3, 6, 9)
说明:
map 含义: 把 Array(1,2,3) 中的每个元素,作为x的参数值,传递给map的函数
scala> Array(1,2,3).map(_ * 3)
res3: Array[Int] = Array(3, 6, 9)
说明:
(x:Int) => x * 3 简写成 _ * 3
(_,1)
(x:Int) => (x,1)
(_,1)
3.带函数参数的函数,即:高阶函数
高阶函数:带有函数参数的函数。把一个函数作为另一个函数的参数值。
定义一个普通函数:
def fun1(name123 : String) : String = "Hello " + name123
定义一个高阶函数
对10进行某种运算
def someAction(func : (Double) => Double) = func(10)
scala> def someAction(f : (Double) => Double) = f(10)
someAction: (f: Double => Double)Double
scala> someAction(sin)
<console>:13: error: not found: value sin
someAction(sin)
^
scala> import scala.math._
import scala.math._
scala> someAction(sin)
res5: Double = -0.5440211108893698
scala> someAction(sqrt)
res6: Double = 3.1622776601683795
scala> someAction(cos)
res7: Double = -0.8390715290764524
4.高阶函数示例
scala为我们提供了一些比较有用的高阶函数
foreach(println)
map((_,1))
(*)map:相当于一个循环,对某个集合中的每个元素进行 操作(接收一个函数),返回一个新的集合
举例:
scala> var numbers = List(1,2,3,4,5,6,7,8,9,10)
numbers: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> numbers.
!= copyToArray grouped maxBy
reverseIterator toArray
## copyToBuffer hasDefiniteSize min
reverseMap toBuffer
+ corresponds hashCode minBy
reverse_::: toIndexedSeq
++ count head mkString
runWith toIterable
++: diff headOption ne
sameElements toIterator
+: distinct indexOf nonEmpty scan
toList
-> drop indexOfSlice notify
scanLeft toMap
/: dropRight indexWhere notifyAll
scanRight toParArray
:+ dropWhile indices orElse
segmentLength toSeq
:: endsWith init padTo seq
toSet
::: ensuring inits par size
toStream
:\ eq intersect partition slice
toString
== equals isDefinedAt patch
sliding toTraversable
WithFilter exists isEmpty permutations sortBy
toVector
addString filter isInstanceOf prefixLength
sortWith transpose
aggregate filterNot isTraversableAgain product sorted
union
andThen find iterator productArity span
unzip
apply flatMap last productElement
splitAt unzip3
applyOrElse flatten lastIndexOf productIterator
startsWith updated
asInstanceOf fold lastIndexOfSlice productPrefix
stringPrefix view
canEqual foldLeft lastIndexWhere reduce sum
wait
collect foldRight lastOption reduceLeft
synchronized withFilter
collectFirst forall length reduceLeftOption tail
zip
combinations foreach lengthCompare reduceOption tails
zipAll
companion formatted lift reduceRight take
zipWithIndex
compose genericBuilder map reduceRightOption
takeRight →
contains getClass mapConserve repr
takeWhile
containsSlice groupBy max reverse to
scala> numbers.map((i:Int) => i * 2)
res8: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
scala> numbers.map(_ * 2)
res9: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
scala> numbers
res10: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
注意:
1、并不改变numbers值
2、返回一个新的集合
(*)foreach
相当于一个循环,对集合中的每个元素进行操作(接收一个函数),不返回结果
scala> numbers
res11: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> numbers.foreach(_*2)
scala> numbers.foreach(print)
12345678910
scala> numbers.foreach(println)
1
2
3
4
5
6
scala> numbers.foreach(println(_))
1
2
3
4
5
6
7
8
9
10
scala> numbers.map(_*2).foreach(println)
2
4
6
8
10
12
14
16
18
20
scala> numbers.foreach(println(_*2))
<console>:16: error: missing parameter type for expanded function ((x$1) =>
x$1.$times(2))
numbers.foreach(println(_*2))
报错原因:
println不是一个高阶函数,不能接收一个函数作为参数
(*)filter:过滤,选择满足的数据
举例:
查询能够被2整除的数字
scala> numbers
res21: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> numbers.filter((i:Int)=>i%2==0)
res22: List[Int] = List(2, 4, 6, 8, 10)
scala> numbers.filter((i:Int)=>i%3==0)
res23: List[Int] = List(3, 6, 9)
scala> numbers.filter(_%2)
<console>:16: error: type mismatch;
found : Int
required: Boolean
numbers.filter(_%2)
^
scala> numbers.filter(_%2==0)
res25: List[Int] = List(2, 4, 6, 8, 10)
(*)zip:合并两个集合
scala> numbers.zip(List(100,200,399))
res26: List[(Int, Int)] = List((1,100), (2,200), (3,399))
scala> List(1,2,3).zip(List(4,5,6))
res27: List[(Int, Int)] = List((1,4), (2,5), (3,6))
scala> List(1,2,3).zip(List(4,5))
res28: List[(Int, Int)] = List((1,4), (2,5))
scala> List(1,2,3).zip(List(4,5,6,7))
res29: List[(Int, Int)] = List((1,4), (2,5), (3,6))
(*)partition:根据断言(就是某个条件,可以通过一个匿名函数来实现)的结果进行分区
scala> numbers
res30: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> numbers.partition((i:Int)=>i%2==0)
res31: (List[Int], List[Int]) = (List(2, 4, 6, 8, 10),List(1, 3, 5, 7, 9))
scala> numbers.partition((i:Int)=>i%3==0)
res32: (List[Int], List[Int]) = (List(3, 6, 9),List(1, 2, 4, 5, 7, 8, 10))
(*)find:查找第一个满足断言的元素
scala> numbers.find(_%3==0)
res34: Option[Int] = Some(3)
scala> numbers.find(_%2==0)
res35: Option[Int] = Some(2)
scala> numbers.find(_%20==0)
res36: Option[Int] = None
(*)flatten:把嵌套的结果展开
scala> List(List(1,2,3,4,5),List(6,7,8,9,10)).flatten
res37: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
合并成一个集合
(*)flatMap:map + flatten
.flatMap(_.split(" "))
scala> var myList = List(List(1,2,3,4,5),List(6,7,8,9,10))
myList: List[List[Int]] = List(List(1, 2, 3, 4, 5), List(6, 7, 8, 9, 10))
scala> myList.flatMap(x => x.map(_*2))
res38: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
执行过程:
1、将List(1, 2, 3, 4, 5) 和 List(6, 7, 8, 9, 10) 调用 x => x.map(_*2) 即 x 代表某
个List
结果 List(List(2,4,6,8,10),List(12,14,16,18,20))
2、合并成一个List flatten
结果:List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
5.闭包
就是函数的嵌套,即:在一个函数定义中,包含另外一个函数的定义;并且在内函数中可以访问外函数中的变量。
def mulBy(factor:Double) = (x:Double) => x*factor
外 内
scala> def mulBy(factor:Double) = (x:Double) => x*factor
mulBy: (factor: Double)Double => Double
scala> val triple = mulBy(3)
triple: Double => Double = <function1>
scala> triple(10)
res39: Double = 30.0
scala> val half = mulBy(0.5)
half: Double => Double = <function1>
scala> half(10)
res40: Double = 5.0
6.柯里化:Currying
柯里是一个科学家
柯里化函数(Curried Function)是把具有多个参数的函数转换为一条函数链,每个节点上是单一参数。
def add(x:Int,y:Int)=x+y
def add(x:Int)(y:Int) = x+y
以上两个函数等价
为什么?
普通函数:
def add(x:Int,y:Int)=x+y
柯里化函数:
def add(x:Int) = (y:Int) => x + y
简写
def add(x:Int)(y:Int) = x + y
def add(x:Int)(y:Int)=x+y
scala> def add(x:Int)(y:Int) = x + y
add: (x: Int)(y: Int)Int
scala> add(1)(2)
res42: Int = 3