三.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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341

推荐阅读更多精彩内容

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