三.Scala语言的函数式编程

函数式编程:程序简单

//举例:实现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

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 首页 资讯 文章 资源 小组 相亲 登录 注册 首页 最新文章 IT 职场 前端 后端 移动端 数据库 运维 其他...
    Helen_Cat阅读 3,955评论 1 10
  • FP 3.1.函数 函数的地位和一般的变量是同等的,可以作为函数的参数,可以作为返回值。传入函数的任何输入是只读的...
    时待吾阅读 1,117评论 0 2
  • Scala的集合类可以从三个维度进行切分: 可变与不可变集合(Immutable and mutable coll...
    时待吾阅读 5,867评论 0 4
  • 数组是一种可变的、可索引的数据集合。在Scala中用Array[T]的形式来表示Java中的数组形式 T[]。 v...
    时待吾阅读 1,003评论 0 0
  • scala学习笔记 第2章 变量和数据类型 基本数据 scala的核心数据为四种 :字面量、值、变量、类型 值使...
    485b1aca799e阅读 2,165评论 0 1