Spark基础-scala学习(四)

函数式编程

  1. 将函数赋值给变量
  2. 匿名函数
  3. 高阶函数
  4. 高级函数的类型推断
  5. scala的常用高阶函数
  6. 闭包
  7. sam转换
  8. currying函数
  9. return

将函数赋值给变量

  1. scala中的函数是一等公民,可以独立定义,独立存在,而且可以直接将函数作为值赋值给变量
scala> def sayHello(name:String){println("Hello, "+name)}
sayHello: (name: String)Unit

scala> sayHello("tom")
Hello, tom

scala> val sayHelloFunc = sayHello _
sayHelloFunc: String => Unit = $$Lambda$1061/[email protected]

scala> sayHelloFunc("leo")
Hello, leo

匿名函数

  1. scala中,函数也可以不需要命名,此时函数被称为匿名函数
  2. 可以直接定义函数后,将函数赋值给某个变量;也可以将直接定义的匿名函数传入其他函数之中
  3. scala定义匿名函数的语法规则就是,(参数名:参数类型)=>函数体
scala> val sayHelloFunc = (name:String) => println("hello, "+name)
sayHelloFunc: String => Unit = $$Lambda$1070/[email protected]

scala> sayHelloFunc("leo")
hello, leo

高阶函数

  1. scala中函数时一等公民,因此可以直接将某个函数传入其他函数,作为参数。这个功能是及其强大的,也是java这种面向对象的编程语言所不具备的
  2. 接收其他函数作为参数的函数,也被称为高阶函数(higher-order function)
scala> val sayHelloFunc = (name:String)=>println("Hello, "+name)
sayHelloFunc: String => Unit = $$Lambda$1167/[email protected]

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

scala> greeting(sayHelloFunc,"leo")
Hello, leo
scala> Array(1,2,3,4,5).map((num:Int)=>num*num)
res5: Array[Int] = Array(1, 4, 9, 16, 25)
  1. 高阶函数的另外一个功能是将函数作为返回值
scala> def getGreetingFunc(msg:String)=(name:String)=>println(msg+","+name)
getGreetingFunc: (msg: String)String => Unit

scala> val greetingFunc = getGreetingFunc("hello")
greetingFunc: String => Unit = $$Lambda$1292/[email protected]

scala> greetingFunc("leo")
hello,leo

高阶函数的类型推断

  1. 高阶函数可以自动判断出参数类型,而不需要写明类型;而且对于只有一个参数的函数,还可以省去其小括号;如果仅有的一个参数在右侧的函数体内只使用一次,则还可以将接收参数省略,并且将参数用_来替代
scala> def greeting(func:(String)=>Unit,name:String){func(name)}
greeting: (func: String => Unit, name: String)Unit

scala> greeting((name:String)=>println("Hello, "+name),"leo")
Hello, leo

scala> greeting((name)=>println("Hello, "+name),"leo")
Hello, leo

scala> greeting(name => println("Hello, "+name),"leo")
Hello, leo

scala> def triple(func:(Int)=>Int) = {func(3)}
triple: (func: Int => Int)Int

scala> triple(3* _)
res10: Int = 9

scala> triple(2+_)
res11: Int = 5

scala的常用高阶函数

scala> Array(1,2,3,4,5).map(2* _)
res13: Array[Int] = Array(2, 4, 6, 8, 10)

scala> (1 to 9).map("*"*_).foreach(println _)
*
**
***
****
*****
******
*******
********
*********

scala> (1 to 20).filter(_ % 2 == 0)
res16: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)

//从左侧元素开始,进行reduce操作,即先对元素1和元素2进行处理,然后将结果与元素3处理,再将结果与元素4处理,依次类推,即为reduce
// 1*2*3*4*5*6*7*8*9
scala> (1 to 9).reduceLeft(_*_)
res17: Int = 362880

//sortWith:对元素进行两两相比,进行排序
scala> Array(3,2,5,4,10,1).sortWith(_ < _)
res19: Array[Int] = Array(1, 2, 3, 4, 5, 10)

闭包

  1. 闭包最简洁的解释,函数在变量不处于其有效作用域时,还能够对变量进行访问,即为闭包
scala> def getGreetingFunc(msg:String) = (name:String)=>println(msg+","+name)
getGreetingFunc: (msg: String)String => Unit

scala> val greetingFuncHello = getGreetingFunc("hello")
greetingFuncHello: String => Unit = $$Lambda$1377/[email protected]

scala> val greetingFuncHi = getGreetingFunc("hi")
greetingFuncHi: String => Unit = $$Lambda$1377/11634[email protected]

scala> greetingFuncHello("leo")
hello,leo

scala> greetingFuncHi("leo")
hi,leo
  1. 两次调用getGreetingFunc函数,传入不同的msg,并创建不同的函数返回
  2. 然而,msg只是一个局部变量,却在getGreetingFunc执行完之后,还可以继续存在创建的函数之中,greetingFuncHello("leo")调用时,值为"hello"的msg被保留在了函数体内部,可以反复的使用
  3. 这种变量超出了其作用域,还可以使用的情况,即为闭包
  4. scala通过为每个函数创建对象来实现闭包,实际上对于getGreetingFunc函数创建的函数,msg是作为函数对象的变量存在的,因此每个函数才可以拥有不同的msg
  5. scala编译器会确保上述闭包机制

SAM转换

  1. 在java中,不支持直接将函数传入一个方法作为参数,通常来说,唯一的办法就是定义一个实现了某个接口的类的实例对象,该对象只有一个方法;而这些接口都只有单个的抽象方法,也就是single abstract method,简称SAM
  2. 由于scala是可以调用java的代码的,因此当我们调用java的某个方法时,可能就不得不创建SAM传递给方法,非常麻烦;但是scala又是支持直接传递函数的。此时就可以使用scala提供的,在调用java方法时,使用的功能,SAM转换,即将SAM转换为scala函数
  3. 要使用SAM转换,需要使用scala提供的特性,隐式转换
scala> import javax.swing._
import javax.swing._

scala> import java.awt.event._
import java.awt.event._

scala> val button = new JButton("Click")

scala> button.addActionListener(new ActionListener{
     | override def actionPerformed(event:ActionEvent){
     |  println("Click Me!!")
     | }
     | })
//隐式转换
scala> implicit def getActionListener(actionProcessFunc:(ActionEvent)=>Unit)=new ActionListener{
     |  override def actionPerformed(event:ActionEvent){
     |   actionProcessFunc(event)
     |  }
     | }

scala> button.addActionListener((event:ActionEvent)=>println("Click Me!!!"))

Currying函数

  1. Curring函数,指的是,将原来接收两个参数的一个函数,转换为两个函数,第一个函数接收原先的第一个参数,然后返回接收原来第二个参数的第二个函数
  2. 在函数调用的过程中,就变为了两个函数去连续调用的形式
scala> def sum(a:Int,b:Int) = a+b
sum: (a: Int, b: Int)Int

scala> sum(1,2)
res24: Int = 3

scala> def sum2(a:Int) = (b:Int)=>a+b
sum2: (a: Int)Int => Int

scala> sum2(1)(2)
res25: Int = 3

scala> def sum3(a:Int)(b:Int) = a+b
sum3: (a: Int)(b: Int)Int

scala> sum3(1)(2)
res26: Int = 3

return

  1. scala中,不需要使用return来返回函数的值,函数最后一行语句的值,就是函数的返回值。在scala中,return用于在匿名函数中返回值给包含匿名函数的带名函数,并作为带名函数的返回值
  2. 使用return的匿名函数,是必须给出返回类型的,否则无法通过编译
scala> :paste
// Entering paste mode (ctrl-D to finish)

def greeting(name:String)={
 def sayHello(name:String):String={
  return "Hello, "+name
 }
 sayHello(name)
}

// Exiting paste mode, now interpreting.

greeting: (name: String)String

scala> greeting("leo")
res27: String = Hello, leo

原文地址:https://www.cnblogs.com/sky-chen/p/10105445.html

时间: 2024-10-14 09:04:43

Spark基础-scala学习(四)的相关文章

Spark基础-scala学习(三)

面向对象编程之Trait trait基础知识 将trait作为接口使用 在trait中定义具体方法 在trait中定义具体字段 在trait中定义抽象字段 trait高级知识 为实例对象混入trait trait调用链 在trait中覆盖抽象方法 混合使用trait的具体方法和抽象方法 trait的构造机制 trati字段的初始化 让trait继承类 将trait作为接口使用 trait作为接口,和java中的接口非常类似 在triat中可以定义抽象方法,就与抽象类中的抽象方法一样,只要不给出方

Spark基础-scala学习(一)

Scala解析器的使用 REPL:Read(取值)-> Evaluation(求值)-> Print(打印)->Loop(循环).scala解析器也被称为REPL,会快速编译scala代码为字节码,然后交给JVM执行 val result = 1 设置变量不可变 var result = 2 可变的变量 val name: String = null 声明变量类型 val name: Any = "leo" val name1,name2:String = null

Spark基础-scala学习(五、集合)

集合 scala的集合体系结构 List LinkedList Set 集合的函数式编程 函数式编程综合案例:统计多个文本内的单词总数 scala的集合体系结构 scala中的集合体系主要包括:Iterable.Seq.Set.Map.其中Iterable是所有集合trait的根trait.这个结构与java的集合体系非常相似 scala中的集合是分成可变和不可变两类集合的,其中可变集合就是说,集合的元素可以动态修改,而不可变集合的元素在初始化之后,就无法修改了.分别对应scala.collec

Spark基础-scala学习(七、类型参数)

类型参数是什么 类似于java泛型,泛型类 泛型函数 上边界Bounds 下边界 View Bounds Context Bounds Manifest Context Bounds 协变和逆变 Existential Type 泛型类 scala> :paste // Entering paste mode (ctrl-D to finish) class Student[T](val localId:T){ def getSchoolId(hukouId:T) = "S-"+

Spark之Scala学习

1. Scala集合学习: http://blog.csdn.net/lyrebing/article/details/20362227 2. scala实现kmeans算法 http://www.thinksaas.cn/group/topic/93852/ 3. Spark之Scala学习网站 http://spark.apache.org/docs/latest/mllib-decision-tree.html 4. Spark wordcount开发并提交到集群运行: http://ww

Scala学习(四)---映射和元组

映射和元组 摘要: 一个经典的程序员名言是:"如果只能有一种数据结构,那就用哈希表吧".哈希表或者更笼统地说映射,是最灵活多变的数据结构之一.映射是键/值对偶的集合.Scala有一个通用的叫法:元组,即n个对象的聚集,并不一定要相同类型的.对偶不过是一个 n=2的元组,元组对于那种需要将两个或更多值聚集在一起时特别有用.本篇的要点包括: 01. Scala有十分易用的语法来创建.查询和遍历映射. 02. 你需要从可变的和不可变的映射中做出选择. 03. 默认情况下,你得到的是一个哈希映射,不过你

Scala学习(四)练习

映射和元组&练习 1. 设置一个映射,其中包含你想要的一些装备,以及它们的价格.然后构建另一个映射,采用同一组键,但在价格上打9折 映射代码如下: object HelloScala{ def main(args: Array[String]): Unit = { val map=Map("Computer"->3000,"Iphone"->2000,"Cup"->10) val fold=for((k,v)<-m

Swift3.0基础语法学习&lt;四&gt;

协议和扩展: // // ViewController4.swift // SwiftBasicDemo // // Created by 思 彭 on 16/11/16. // Copyright ? 2016年 思 彭. All rights reserved. // 协议和扩展 import UIKit // 定义协议 protocol ExampleProtocol { var simpleDescription: String { get } // 使用 mutating 关键字修饰方

Spark学习四:网站日志分析案例

Spark学习四:网站日志分析案例 标签(空格分隔): Spark Spark学习四网站日志分析案例 一创建maven工程 二创建模板 三日志分析案例 一,创建maven工程 1,执行maven命令创建工程 mvn archetype:generate -DarchetypeGroupId=org.scala-tools.archetypes -DarchetypeArtifactId=scala-archetype-simple -DremoteRepositories=http://scal