scala(一)方法&函数
写在前面
众所周知,scala一向宣称自己是面向函数的编程,(java表示不服,我是面向bean的编程!)那什么是函数?
在接触java的时候,有时候用函数来称呼某个method(实在找不出词了),有时候用方法来称呼某个method,虽然method的中文翻译就是“方法”,但对于java来说,方法和函数是等价的,或者说没有函数这个概念。
而对于scala,这两者似乎有一个较为明确的边界。
你会发现满世界的函数,而你却在写方法
Scala 方法&函数
方法
Scala的方法和java可以看成是一样的,只是多了点语法糖。
比如无参方法在申明时可以不加括号,甚至在调用过程也不用加括号
def f = 1+1
println(f)
比如方法可以添加泛型规则,这在java中只能在类申明
def f[T](t: T) = {t}
还有其它很多细节语法,遇到才深入吧
一般而言只要知道函数的结构就行(但是我想说,spark的代码就没有一个函数长成这样的啊..),请忽略下图的“函数”字样,其实就是方法

方法应用
def method(): Unit ={
//本地方法
def print(str:String): Unit ={
println(str)
}
print("hello")
}
方法的语法还是跟java差不多的,只是有些可以省略而已。
比较重要的就是本地方法,即方法中嵌套方法
函数
Scala的函数是基于Function家族,0-22,一共23个Function Trait可以被使用,数字代表了Funtcion的入参个数
函数语法
下面这四个函数的意义是一样的
// println(fun1)
// println(fun2)
// println(fun3)
// println(fun4)
// 都为<function2>
val fun1 = new Function2[Int,Int,Int]() {
override def apply(v1: Int, v2: Int): Int = {
v1+v2
}
} val fun2 = new ((Int, Int) => Int)() {
override def apply(v1: Int, v2: Int): Int = {
v1+v2
}
} val fun3 = (v1:Int,v2:Int) => v1+v2 // _可以把method转换成function
val fun4 = fun4Method _
def fun4Method(v1:Int,v2:Int): Int = {
v1+v2
}
一般我们都采用第三种fun3定义方式,也是最难懂的一个定义方式。具体结构参考下图

那函数有什么用呢?
Java里只有方法都能适应一切需求,那scala又提出函数的概念肯定有意义。
1.函数可以直接赋值给变量,可以让函数很方便的传递
2.闭包(closure),可以把灵活操作代码块,从而引申出其他灵活的语法
函数应用
在spark中,有很多方法入参中使用函数的场景,比如如下函数
defrunJob[T,U](fun: Iterator[T] => U ,resHandler: (Int, U) => Unit): Unit ={
//忽略里面的逻辑
}
其中的fun和resHandler都是函数
Fun是入参为Iterator[T],返回值为U的函数,一个入参的函数其实就是Function1的实例
resHandler是入参为Int和 U无返回值的函数,二个入参的函数其实就是Function2
模拟spark中常见的一段代码语法,拿一个普通scala类型的例子来说
//模拟spark的runJob方法
def runJob[T,U](fun: Iterator[T] => U ,resHandler: (Int, U) => Unit): Unit ={
val listBuffer = new ListBuffer[T]
listBuffer.append("h".asInstanceOf[T])
listBuffer.append("e".asInstanceOf[T])
listBuffer.append("l".asInstanceOf[T])
listBuffer.append("l".asInstanceOf[T])
listBuffer.append("o".asInstanceOf[T])
//这里调用函数其实用到了伴生对象的概念,fun(xxx)就是fun.apply(xxx)
val res = fun(listBuffer.iterator)
//spark中,这里是每个partition的数据都存入arr,这里做模拟就一个partition了:)
resHandler(0,res)
} //模拟调用runJob的方法
def main(args: Array[String]): Unit = {
val arr = new Array[String](1)
//fun函数的实际逻辑
val fun = (it:Iterator[String]) => {
val sb = new StringBuilder()
while (it.hasNext)
sb.append(it.next())
sb.toString()
} //resHandler函数的实际逻辑
val resHandler = (i:Int,res:String) => arr(i) = res
runJob[String,String](fun ,resHandler)
println(arr.mkString(""))
}
其实就是传递函数的逻辑,和java的匿名类差不多(只有一个方法的匿名类),只是多了点语法糖
这么做的好处也是不言而喻的
1.可以构造出更抽象的方法,使得代码结构更简洁
2.spark的思想就是lazy,而函数传递也是一个lazy的过程,只有在实际触发才会执行
偏函数
英文为PartialFunction,不知道这么翻译对不对,貌似都这么叫。
PartialFunction其实是Funtion1的子类
参考源码
trait PartialFunction[-A, +B] extends (A => B)
A => B就是标准的函数结构
那PartialFunction有什么作用呢?
模式匹配!
PartialFunction最重要的两个方法,一个是实际的操作逻辑,一个是校验,其实就是用来做模式匹配的。
参考资料
《Scala编程》
scala(一)方法&函数的更多相关文章
- 【Scala篇】--Scala中的函数
一.前述 Scala中的函数还是比较重要的,所以本文章把Scala中可能用到的函数列举如下,并做详细说明. 二.具体函数 1.Scala函数的定义 def fun (a: Int , b: Int ) ...
- Scala函数式编程(三) scala集合和函数
前情提要: scala函数式编程(二) scala基础语法介绍 scala函数式编程(二) scala基础语法介绍 前面已经稍微介绍了scala的常用语法以及面向对象的一些简要知识,这次是补充上一章的 ...
- Scala高阶函数与泛型
1. Scala中的函数 在Scala中,函数是“头等公民”,就和数字一样.可以在变量中存放函数,即:将函数作为变量的值(值函数). 2. scala中的匿名函数,即没有函数名称的函数,匿名函数常作为 ...
- scala def方法时等号和括号使用说明笔记
scala定义方法时会指定入参和返回类型(无返回类型时对应Unit,即java和C中的void模式). 1.有入参,有返回类型时,scala具有类型推导功能,以下两种表达方式效果一样.但根据scala ...
- scala编程(八)——函数和闭包
当程序变得庞大时,你需要一些方法把它们分割成更小的,更易管理的片段.为了分割控制流,Scala 提供了所有有经验的程序员都熟悉的方式:把代码分割成函数.实际上,Scala 提供了许多 Java 中没有 ...
- Scala 深入浅出实战经典 第42讲:scala 泛型类,泛型函数,泛型在spark中的广泛应用
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- <经验杂谈>C#中一种最简单、最基本的反射(Reflection):通过反射获取方法函数
说起反射之前和很多用C#/.net的同仁们一样,相比于一般应用层对数据的增删改查总有点觉得深奥到难以理解.其实程序这东西,用过.实践过就很简单,我一直这么认为. 先说下概念:反射 Reflection ...
- Python学习入门基础教程(learning Python)--8.3 字典常用的方法函数介绍
本节的主要讨论内容是有关dict字典的一些常用的方法函数的使用和范例展示. 1. clear清除字典数据 语法结构如下: dict_obj.clear() 示例代码如下: dict1 = {'web' ...
- PHP(方法 函数 循环 和 数组 查找)
循环 和 数组 查找 顺序查找 二分法查找 冒泡排序 方法 函数 定义:一堆代码的集合叫做函数(满足条件下“一堆”) 语法,定义,调用,参数列表(形参,实参),返回值 两种方法: function 方 ...
随机推荐
- UISearchBar 详解
UISearchBar 详解 最近用到搜索功能.于是,经过不断的研究,终于,有点懂了. 那就来总结一下吧,好记性不如烂笔头! 搜索,无疑可以使用UISearchBar控件! 那就先了解一下UISe ...
- 自建YUM仓库
YUM主要用于自动安装.升级rpm软件包,它能自动查找并解决rpm包之间的依赖关系. 要成功的使用YUM工具安装更新软件或系统,就需要有一个包含各种rpm软件包的repository(软件仓库),这个 ...
- kvm_read_guest*函数分析
2017-06-30 在KVM中基于其搞特权及,可以透明的读写客户机的内存信息,为此KVM提供了一套API,这里姑且称之为kvm_read_guest_virt*/kvm_write_guest_vi ...
- 在django项目中手动模拟实现settings的配置
一 文件结构目录 手写配置文件 有两套配置文件,默认配置,用户的配置 如果某个字段,用户配置了,就用用户的,如果没配置,就用默认的 1.1 test import os os.environ.se ...
- (转)Linux下配置tomcat+apr+native应对高并发
摘要:在慢速网络上Tomcat线程数开到300以上的水平,不配APR,基本上300个线程狠快就会用满,以后的请求就只好等待.但是配上APR之后,Tomcat将以JNI的形式调用Apache HTTP服 ...
- sscanf,sscanf
在#include<stdio.h> 定义函数 int sscanf (const char *str,const char * format,........); 函数说明: sscan ...
- windows计划任务定时运行synctoy的坑
每次设置好synctoy之后,需要让synctoy运行一次,windows的计划任务才能成功执行,如果变更了synctoy的设置,而没有让synctoy成功执行过,windows计划任务将执行失败,坑 ...
- Jenkins的权限控制和Rundeck的远程认证
1.权限控制的基本设置 1.1选择基于角色权限的分配策略 1.2 配置全局权限和项目权限 具体的权限对应关系见下表: Overall(全局) Credentials(凭证) Slave(节点) Job ...
- Windows资源监控神器——perfmon
一.简述 笔者在用lr中control监控Windows资源的时候,有时候总是遇到卡死和报错,所以就发现了Windows自带的监控神器————perfmon. Perfmon提供了图表化的系统性能实时 ...
- spark[源码]-TaskSchedulerlmpl类源码
TaskSchedulerImpl概述 TaskSchedulerlmpl是创建三大核心TaskSheduler的实现类,TaskScheduler是一个特征类,DAGScheduler在提交Task ...