01.Scala编程基础
Scala编程
1. 课程目标..................................................................................................................... 2
1.1. 目标1:(初级)熟练使用scala编写Spark程序.............................................. 2
1.2. 目标2:(中级)动手编写一个简易Spark通信框架......................................... 3
1.3. 目标3:(高级)为阅读Spark内核源码做准备................................................ 4
2. Scala概述..................................................................................................................... 4
2.1. 什么是Scala...................................................................................................... 4
2.2. 为什么要学Scala............................................................................................... 4
3. Scala编译器安装.......................................................................................................... 5
3.1. 安装JDK............................................................................................................ 5
3.2. 安装Scala.......................................................................................................... 5
3.2.1. Windows安装Scala编译器....................................................................... 5
3.2.2. Linux安装Scala编译器............................................................................. 5
3.2.3. Scala开发工具安装................................................................................... 6
4. Scala基础..................................................................................................................... 9
4.1. 声明变量........................................................................................................... 9
4.2. 常用类型........................................................................................................... 9
4.3. 条件表达式........................................................................................................ 9
4.4. 块表达式......................................................................................................... 10
4.5. 循环................................................................................................................. 11
4.6. 调用方法和函数............................................................................................... 12
4.7. 定义方法和函数............................................................................................... 12
4.7.1. 定义方法............................................................................................... 12
4.7.2. 定义函数............................................................................................... 13
4.7.3. 方法和函数的区别................................................................................. 13
4.7.4. 将方法转换成函数(神奇的下划线).................................................... 14
5. 数组、映射、元组、集合.......................................................................................... 14
5.1. 数组................................................................................................................. 14
5.1.1. 定长数组和变长数组............................................................................. 14
5.1.2. 遍历数组............................................................................................... 16
5.1.3. 数组转换............................................................................................... 17
5.1.4. 数组常用算法........................................................................................ 17
5.2. 映射................................................................................................................. 18
5.2.1. 构建映射............................................................................................... 18
5.2.2. 获取和修改映射中的值.......................................................................... 18
5.3. 元组................................................................................................................. 19
5.3.1. 创建元组............................................................................................... 19
5.3.2. 获取元组中的值..................................................................................... 20
5.3.3. 将对偶的集合转换成映射...................................................................... 20
5.3.4. 拉链操作............................................................................................... 20
5.4. 集合................................................................................................................. 21
5.4.1. 序列....................................................................................................... 21
5.5. Set.................................................................................................................... 22
5.6. Map.................................................................................................................. 23
6. 类、对象、继承、特质............................................................................................. 24
6.1. 类.................................................................................................................... 24
6.1.1. 类的定义............................................................................................... 24
6.1.2. 构造器................................................................................................... 24
6.2. 对象................................................................................................................. 26
6.2.1. 单例对象............................................................................................... 26
6.2.2. 伴生对象............................................................................................... 27
6.2.3. apply方法............................................................................................... 27
6.2.4. 应用程序对象........................................................................................ 28
6.3. 继承................................................................................................................. 28
6.3.1. 扩展类................................................................................................... 28
6.3.2. 重写方法............................................................................................... 28
6.3.3. 类型检查和转换..................................................................................... 29
6.3.4. 超类的构造............................................................................................ 29
7. 模式匹配和样例类..................................................................................................... 30
7.1. 匹配字符串...................................................................................................... 30
7.2. 匹配类型......................................................................................................... 30
7.3. 匹配数组、元组............................................................................................... 31
7.4. 样例类............................................................................................................. 32
7.5. Option类型....................................................................................................... 32
7.6. 偏函数............................................................................................................. 33
1. 课程目标
1.1. 目标1:(初级)熟练使用scala编写Spark程序
1.2. 目标2:(中级)动手编写一个简易Spark通信框架
1.3. 目标3:(高级)为阅读Spark内核源码做准备
2. Scala概述
2.1. 什么是Scala
Scala是一种多范式的编程语言,其设计的初衷是要集成面向对象编程和函数式编程的各种特性。Scala运行于Java平台(Java虚拟机),并兼容现有的Java程序。
2.2. 为什么要学Scala
1.优雅:这是框架设计师第一个要考虑的问题,框架的用户是应用开发程序员,API是否优雅直接影响用户体验。
2.速度快:Scala语言表达能力强,一行代码抵得上Java多行,开发速度快;Scala是静态编译的,所以和JRuby,Groovy比起来速度会快很多。
- 能融合到Hadoop生态圈:Hadoop现在是大数据事实标准,Spark并不是要取代Hadoop,而是要完善Hadoop生态。JVM语言大部分可能会想到Java,但Java做出来的API太丑,或者想实现一个优雅的API太费劲。
3. Scala编译器安装
3.1. 安装JDK
因为Scala是运行在JVM平台上的,所以安装Scala之前要安装JDK
3.2. 安装Scala
3.2.1. Windows安装Scala编译器
访问Scala官网http://www.scala-lang.org/下载Scala编译器安装包,目前最新版本是2.12.x,但是目前大多数的框架都是用2.10.x编写开发的,所以这里推荐2.10.x版本,下载scala-2.10.6.msi后点击下一步就可以了
3.2.2. Linux安装Scala编译器
下载Scala地址http://downloads.typesafe.com/scala/2.10.6/scala-2.10.6.tgz然后解压Scala到指定目录
tar -zxvf scala-2.10.6.tgz -C /usr/java
配置环境变量,将scala加入到PATH中
vi /etc/profile
export JAVA_HOME=/usr/java/jdk1.7.0_45
export PATH=$PATH:$JAVA_HOME/bin:/usr/java/scala-2.10.6/bin
3.2.3. Scala开发工具安装
目前Scala的开发工具主要有两种:Eclipse和IDEA,这两个开发工具都有相应的Scala插件,如果使用Eclipse,直接到Scala官网下载即可http://scala-ide.org/download/sdk.html。
由于IDEA的Scala插件更优秀,大多数Scala程序员都选择IDEA,可以到http://www.jetbrains.com/idea/download/下载社区免费版,点击下一步安装即可,安装时如果有网络可以选择在线安装Scala插件。这里我们使用离线安装Scala插件:
1.安装IDEA,点击下一步即可。由于我们离线安装插件,所以点击Skip All and Set Defaul
2.下载IEDA的scala插件,地址http://plugins.jetbrains.com/?idea_ce
3.安装Scala插件:Configure -> Plugins -> Install plugin from disk -> 选择Scala插件 -> OK -> 重启IDEA
4. Scala基础
4.1. 声明变量
package cn.itcast.scala //变量名在前,类型在后 |
4.2. 常用类型
Scala和Java一样,有7种数值类型Byte、Char、Short、Int、Long、Float和Double(无包装类型)和一个Boolean类型
4.3. 条件表达式
Scala的的条件表达式比较简洁,例如:
package cn.itcast.scala |
4.4. 块表达式
package cn.itcast.scala |
4.5. 循环
Scala中没有提到过continue和break,用if替换每个continue和用布尔变量替换每个break。
在scala中有for循环和while循环,用for循环比较多
for循环语法结构:for (i <- 表达式/数组/集合)
package cn.itcast.scala //每次循环将区间中的一个值赋给i //每次迭代生成集合中的一个值 |
4.6. 调用方法和函数
Scala中的+ - * / %等操作符的作用与Java一样,位操作符 & | ^ >> <<也一样。只是有
一点特别的:这些操作符实际上是方法。例如:
a + b
是如下方法调用的简写:
a.+(b)
a 方法 b可以写成 a.方法(b)
4.7. 定义方法和函数
4.7.1. 定义方法
scala里方法参数的一个重要特征就是他们都是val;
如果方法某个方法仅计算单个结果表达式,则可以省略花括号:def add(b: Int):Unit = sum+=b
对于方法的结果类型为Unit的方法,执行的目的就是为了它的副作用。通常我们定义副作用为能够改变方法之外的状态或执行I/O活动的方法;
方法的返回值类型可以不写,编译器可以自动推断出来,但是对于递归函数,必须指定返回类型;
注意:比较容易出错的地方是如果去掉方法体前面的=,那么方法的结果类型必定是Unit。无论方法体包含什么都成立,因为Scala编译器可以把任何类型转换为Unit:
scala> def f(): Unit = "this String gets lost"
<console>:11: warning: a pure expression does nothing in statement position
def f(): Unit = "this String gets lost"
^
f: ()Unit
函数f声明了结果类型为Unit,因此String被转换为Unit
scala> def g() {"this String gets lost too"}
<console>:11: warning: a pure expression does nothing in statement position
def g() {"this String gets lost too"}
^
g: ()Unit
Scala会把定义像过程的方法(带有花括号但没有等号),本质上当作Unit结果类型的方法。
4.7.2. 定义函数
4.7.3. 方法和函数的区别
在函数式编程语言中,函数是“头等公民”,它可以像任何其他数据类型一样被传递和操作
案例:首先定义一个方法,再定义一个函数,然后将函数传递到方法里面
函数字面量:
(x:Int) => x+1
package cn.itcast.scala //返回值类型也是Int类型 |
4.7.4. 将方法转换成函数(神奇的下划线)
5. 数组、映射、元组、集合
5.1. 数组
5.1.1. 定长数组和变长数组
package cn.itcast.scala |
5.1.2. 遍历数组
1.增强for循环
2.好用的until会生成脚标,0 until 10 包含0不包含10
package cn.itcast.scala |
5.1.3. 数组转换
yield关键字将原始的数组进行转换会产生一个新的数组,原始的数组不变
package cn.itcast.scala |
5.1.4. 数组常用算法
在Scala中,数组上的某些方法对数组进行相应的操作非常方便!
5.2. 映射
在Scala中,把哈希表这种数据结构叫做映射
5.2.1. 构建映射
5.2.2. 获取和修改映射中的值
好用的getOrElse
注意:在Scala中,有两种Map,一个是immutable包下的Map,该Map中的内容不可变;另一个是mutable包下的Map,该Map中的内容可变
例子:
注意:通常我们在创建一个集合是会用val这个关键字修饰一个变量(相当于java中的final),那么就意味着该变量的引用不可变,该引用中的内容是不是可变,取决于这个引用指向的集合的类型
5.3. 元组
映射是K/V对偶的集合,对偶是元组的最简单形式,元组可以装着多个不同类型的值。
5.3.1. 创建元组
5.3.2. 获取元组中的值
5.3.3. 将对偶的集合转换成映射
5.3.4. 拉链操作
zip命令可以将多个值绑定在一起
注意:如果两个数组的元素个数不一致,拉链操作后生成的数组的长度为较小的那个数组的元素个数
5.4. 集合
Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质
在Scala中集合有可变(mutable)和不可变(immutable)两种类型,immutable类型的集合初始化后就不能改变了(注意与val修饰的变量进行区别)
5.4.1. 序列
不可变的序列 import scala.collection.immutable._
在Scala中列表要么为空(Nil表示空列表)要么是一个head元素加上一个tail列表。
9 :: List(5, 2) :: 操作符是将给定的头和尾创建一个新的列表
注意::: 操作符是右结合的,如9 :: 5 :: 2 :: Nil相当于 9 :: (5 :: (2 :: Nil))
package cn.itcast.collect |
可变的序列 import scala.collection.mutable._
package cn.itcast.collect |
5.5. Set
不可变的Set
package cn.itcast.collect |
可变的Set
package cn.itcast.collect |
5.6. Map
package cn.itcast.collect |
6. 类、对象、继承、特质
Scala的类与Java、C++的类比起来更简洁,学完之后你会更爱Scala!!!
6.1. 类
6.1.1. 类的定义
Scala里禁止在同一个类里用同样的名称定义字段和方法,字段和方法不能重名。尽管Java允许这样做。
Java为定义准备了四个命名空间(字段,方法,类型和包),
Scala仅有两个命名空间:
值(字段,方法,包还有单例对象)。
类型(类和特质名)。
Scala把字段和方法放进同一个命名空间的理由很明确:可以实现使用val重写无参数方法。
//在Scala中,类并不用声明为public。 //Scala源文件中可以包含多个类,所有这些类都具有公有可见性。 //(相当与Java中用final修饰的变量) //用var修饰的变量既有getter又有setter //类私有字段,只能在类的内部使用 } |
6.1.2. 构造器
注意:主构造器会执行类定义中的所有语句
Scala编译器将把类内部的任何既不是字段也不是方法定义的代码编译到主构造器中。
关键字this指向当前执行方法被调用的对象实例,或者如果使用在构造器里的话,就是正在被构建的对象实例。
/** this(name, age) |
/** *那么它将会被提升为字段 //在类名后面加private就变成了私有的 |
6.2. 对象
6.2.1. 单例对象
在Scala中没有静态方法和静态字段,但是可以使用object这个语法结构来达到同样的目的
类和单例对象的差别是,单例对象不带参数,而类可以。因为单例对象不能用new关键字实例化,所以没有机会给它实例化参数。每个单例对象都被实现为虚构类(synthetic class)(虚构类的名字是对象名加上一个美元符号)的实例,并指向静态的变量,因此与java静态类有着相同的初始化语义。
注意:单例对象在第一被访问的时候才被初始化。
1.存放工具方法和常量
2.高效共享单个不可变的实例
3.单例模式
package cn.itcast.scala |
6.2.2. 伴生对象
在Scala的类中,与类名相同的对象叫做伴生对象,类和伴生对象之间可以相互访问私有的方法和属性
Scala的每个源文件都隐含了对包java.lang/包scala,以及单例对象PreDef的成员引用。包scala中PreDef对象包含了许多有用的方法。例如,Scala源文件中写下println语句,实际上调用的是PreDef的println(PreDef.println转而调用Console.println,完成真正的工作)。
package cn.itcast.scala |
6.2.3. apply方法
通常我们会在类的伴生对象中定义apply方法,当遇到类名(参数1,...参数n)时apply方法会被调用
package cn.itcast.scala
|
6.2.4. 应用程序对象
Scala程序都必须从一个对象的main方法开始,可以通过扩展App特质,不写main方法。
package cn.itcast.scala |
6.3. 继承
6.3.1. 扩展类
在Scala中扩展类的方式和Java一样都是使用extends关键字
6.3.2. 重写方法
在Scala中重写一个非抽象的方法必须使用override修饰符
Scala要求,若子类成员所有重写了父类的具体成员则必须带有override修饰符;
若成员实现的是同名的抽象成员时,则override是可选的;
若成员并未重写或实现其它基类里的成员,则禁用override。
如果想要一个成员或者类不被子类重写或继承,给成员或类添加final修饰符。
6.3.3. 类型检查和转换
Scala |
Java |
obj.isInstanceOf[C] |
obj instanceof C |
obj.asInstanceOf[C] |
(C)obj |
classOf[C] |
C.class |
6.3.4. 超类的构造
package cn.itcast.scala |
7. 模式匹配和样例类
Scala有一个十分强大的模式匹配机制,可以应用到很多场合:如switch语句、类型检查等。
并且Scala还提供了样例类,对模式匹配进行了优化,可以快速进行匹配
7.1. 匹配字符串
package cn.itcast.cases |
7.2. 匹配类型
package cn.itcast.cases |
注意:case y: Double if(y >= 0) => ...
模式匹配的时候还可以添加守卫条件。如不符合守卫条件,将掉入case _中
7.3. 匹配数组、元组
package cn.itcast.cases |
注意:在Scala中列表要么为空(Nil表示空列表)要么是一个head元素加上一个tail列表。
9 :: List(5, 2) :: 操作符是将给定的头和尾创建一个新的列表
注意::: 操作符是右结合的,如9 :: 5 :: 2 :: Nil相当于 9 :: (5 :: (2 :: Nil))
7.4. 样例类
在Scala中样例类是一中特殊的类,可用于模式匹配。case class是多例的,后面要跟构造参数,case object是单例的
package cn.itcast.cases
|
7.5. Option类型
在Scala中Option类型样例类用来表示可能存在或也可能不存在的值(Option的子类有Some和None)。Some包装了某个值,None表示没有值
package cn.itcast.cases |
7.6. 偏函数
被包在花括号内没有match的一组case语句是一个偏函数,它是PartialFunction[A, B]的一个实例,A代表参数类型,B代表返回类型,常用作输入模式匹配
package cn.itcast.cases
|
02.Actor编程
Scala Actor
1. 课程目标
1.1. 目标一:熟悉Scala Actor并发编程
1.2. 目标二:为学习Akka做准备
注:我们现在学的Scala Actor是scala 2.10.x版本及以前版本的Actor。
Scala在2.11.x版本中将Akka加入其中,作为其默认的Actor,老版本的Actor已经废弃
2. 什么是Scala Actor
2.1. 概念
Scala中的Actor能够实现并行编程的强大功能,它是基于事件模型的并发机制,Scala是运用消息(message)的发送、接收来实现多线程的。使用Scala能够更容易地实现多线程应用的开发。
2.2. 传统java并发编程与Scala Actor编程的区别
对于Java,我们都知道它的多线程实现需要对共享资源(变量、对象等)使用synchronized 关键字进行代码块同步、对象锁互斥等等。而且,常常一大块的try…catch语句块中加上wait方法、notify方法、notifyAll方法是让人很头疼的。原因就在于Java中多数使用的是可变状态的对象资源,对这些资源进行共享来实现多线程编程的话,控制好资源竞争与防止对象状态被意外修改是非常重要的,而对象状态的不变性也是较难以保证的。 而在Scala中,我们可以通过复制不可变状态的资源(即对象,Scala中一切都是对象,连函数、方法也是)的一个副本,再基于Actor的消息发送、接收机制进行并行编程
2.3. Actor方法执行顺序
1.首先调用start()方法启动Actor
2.调用start()方法后其act()方法会被执行
3.向Actor发送消息
2.4. 发送消息的方式
! |
发送异步消息,没有返回值。 |
!? |
发送同步消息,等待返回值。 |
!! |
发送异步消息,返回值是 Future[Any]。 |
3. Actor实战
3.1. 第一个例子
package cn.itcast.actor import scala.actors.Actor object MyActor1 extends Actor{ |
说明:上面分别调用了两个单例对象的start()方法,他们的act()方法会被执行,相同与在java中开启了两个线程,线程的run()方法会被执行
注意:这两个Actor是并行执行的,act()方法中的for循环执行完成后actor程序就退出了
3.2. 第二个例子(可以不断地接收消息)
package cn.itcast.actor
/**
} |
说明:在act()方法中加入了while (true) 循环,就可以不停的接收消息
注意:发送start消息和stop的消息是异步的,但是Actor接收到消息执行的过程是同步的按顺序执行
3.3. 第三个例子(react方式会复用线程,比receive更高效)
package cn.itcast.actor
/**
} |
说明: react 如果要反复执行消息处理,react外层要用loop,不能用while
3.4. 第四个例子(结合case class发送消息)
package cn.itcast.actor |
4. 练习
用actor并发编程写一个单机版的WorldCount,将多个文件作为输入,计算完成后将多个任务汇总,得到最终的结果
package cn.itcast.actor |
03.Scala高级特性
Scala高级特性
1. 课程目标
1.1. 目标一:深入理解高阶函数
1.2. 目标一:深入理解隐式转换
2. 高阶函数
2.1. 概念
Scala混合了面向对象和函数式的特性,我们通常将可以做为参数传递到方法中的表达式叫做函数。在函数式编程语言中,函数是“头等公民”,高阶函数包含:作为值的函数、匿名函数、闭包、柯里化等等。
2.2. 作为值的函数
可以像任何其他数据类型一样被传递和操作的函数,每当你想要给算法传入具体动作时这个特性就会变得非常有用。
定义函数时格式:val 变量名 = (输入参数类型和个数) => 函数实现和返回值类型和个数
“=”表示将函数赋给一个变量
“=>”左面表示输入参数名称、类型和个数,右边表示函数的实现和返回值类型和参数个数
2.3. 匿名函数
在Scala中,你不需要给每一个函数命名,没有将函数赋给变量的函数叫做匿名函数
由于Scala可以自动推断出参数的类型,所有可以写的跟精简一些
还记得神奇的下划线吗?这才是终极方式
2.4. 将方法转换成函数
在Scala中,方法和函数是不一样的,最本质的区别是函数可以做为参数传递到方法中
但是方法可以被转换成函数,神奇的下划线又出场了
2.5. 柯里化
柯里化指的是将原来接受两个参数的方法变成新的接受一个参数的方法的过程
2.6. 例子
package cn.itcast.scala |
3. 隐式转换和隐式参数
3.1. 概念
隐式转换和隐式参数是Scala中两个非常强大的功能,利用隐式转换和隐式参数,你可以提供优雅的类库,对类库的使用者隐匿掉那些枯燥乏味的细节。
3.2. 作用
隐式的对类的方法进行增强,丰富现有类库的功能
3.3. 隐式转换函数
是指那种以implicit关键字声明的带有单个参数的函数
3.4. 隐式转换例子
package cn.itcast.impli |
package cn.itcast.scala |
04.Scala编程实战
Scala编程实战
1. 课程目标
1.1. 目标:熟练使用Scala编写程序
2. 项目概述
2.1. 需求
目前大多数的分布式架构底层通信都是通过RPC实现的,RPC框架非常多,比如前我们学过的Hadoop项目的RPC通信框架,但是Hadoop在设计之初就是为了运行长达数小时的批量而设计的,在某些极端的情况下,任务提交的延迟很高,所有Hadoop的RPC显得有些笨重。
Spark 的RPC是通过Akka类库实现的,Akka用Scala语言开发,基于Actor并发模型实现,Akka具有高可靠、高性能、可扩展等特点,使用Akka可以轻松实现分布式RPC功能。
2.2. Akka简介
Akka基于Actor模型,提供了一个用于构建可扩展的(Scalable)、弹性的(Resilient)、快速响应的(Responsive)应用程序的平台。
Actor模型:在计算机科学领域,Actor模型是一个并行计算(Concurrent Computation)模型,它把actor作为并行计算的基本元素来对待:为响应一个接收到的消息,一个actor能够自己做出一些决策,如创建更多的actor,或发送更多的消息,或者确定如何去响应接收到的下一个消息。
Actor是Akka中最核心的概念,它是一个封装了状态和行为的对象,Actor之间可以通过交换消息的方式进行通信,每个Actor都有自己的收件箱(Mailbox)。通过Actor能够简化锁及线程管理,可以非常容易地开发出正确地并发程序和并行系统,Actor具有如下特性:
1.提供了一种高级抽象,能够简化在并发(Concurrency)/并行(Parallelism)应用场景下的编程开发
2.提供了异步非阻塞的、高性能的事件驱动编程模型
3.超级轻量级事件处理(每GB堆内存几百万Actor)
3. 项目实现
3.1. 架构图
3.2. 重要类介绍
3.2.1. ActorSystem
在Akka中,ActorSystem是一个重量级的结构,他需要分配多个线程,所以在实际应用中,ActorSystem通常是一个单例对象,我们可以使用这个ActorSystem创建很多Actor。
3.2.2. Actor
在Akka中,Actor负责通信,在Actor中有一些重要的生命周期方法。
1.preStart()方法:该方法在Actor对象构造方法执行后执行,整个Actor生命周期中仅执行一次。
2.receive()方法:该方法在Actor的preStart方法执行完成后执行,用于接收消息,会被反复执行。
3.3. Master类
package cn.itcast.spark |
3.4. Worker类
package cn.itcast.spark |
原文地址:https://www.cnblogs.com/skorzeny/p/6686712.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。