玩转scala.docx
- 文档编号:11473653
- 上传时间:2023-03-01
- 格式:DOCX
- 页数:31
- 大小:638.08KB
玩转scala.docx
《玩转scala.docx》由会员分享,可在线阅读,更多相关《玩转scala.docx(31页珍藏版)》请在冰豆网上搜索。
玩转scala
SCALA学习资料
1.Scala基础
1.1.Scala基础
1.1.1.Scala基础
思考点:
序号
知识点
类型
难度系数
掌握程度
1.
有了这么多开发语言,为什么我们需要Scala?
或者说为何Spark要用Scala实现?
概念
1
熟练
2.
面向对象经过这么多年发展已经非常成熟,为何半路杀出个程咬金,函数式编程?
为何我们需要它?
概念
1
熟练
知识点:
序号
知识点
类型
难度系数
掌握程度
3.
Scala基本语法规则使用
基础
1
熟练
4.
Scala环境安装使用,创建Scala工程
基础
1
熟练
5.
什么叫函数式编程,它的好处是什么?
概念
1
熟练
6.
Array和List的区别
概念
1
熟练
7.
常用的集合
Array/List/ArrayBuffer/Set/Map/Tuple
知识
1
熟练
8.
熟练高阶函数partition/map/filter/reduce
/par/groupBy/mapValues
知识
1
熟练
9.
单词统计
代码
1
熟练
1.2.Spark知识了解
1.2.1.背景
Hadoop在处理大数据时非常棒,可以使用一些破机器,普通的PC就可以完成海量数据的存储和计算,但也因为此设计特点,假定硬件设备质量差,性能低,网络环境差而造成“过度”设计。
从而导致它有一个致命弱点,它将中间结果频繁落地。
将数据存放到磁盘,又从磁盘读出。
磁盘IO读写非常耗时,这样导致整个处理时间拉长。
这种选择在当时而言无疑是正确的选择。
但随着硬件越来越便宜,质量性能越来越高,网络越来越快,越来越稳定。
这个问题就凸显出来,性能低。
于是超越的产品ApacheSpark横空出世。
Spark的中间结果中放在内存中不落地。
大部分计算都可以在内存中处理。
它比Hadoop性能就要高很多,官网宣称快100倍之多。
同时Spark使用MR也比Hadoop简单。
1.2.2.特点
●Spark采用Scala语言编写,底层采用actormodel的akka作为通讯框架,代码十分简洁高效。
●基于DAG(有向无环图)的执行引擎,减少多次计算之间中间结果写到HDFS的开销
●建立在统一抽象的RDD(分布式内存抽象)之上,使得它可以以基本一致的方式应对不同的大数据处理场景
●提供Cache机制来支持需要反复迭代的计算或者多次数据共享,减少数据读取的IO开销
●于Hadoop的MapReduce相比,Spark基于内存的运算比MR要快100倍;而基于硬盘的运算也要快10倍
●Spark提供广泛的数据集操作类型(20+种),不像Hadoop只提供了Map和Reduce两种操作
●Spark支持Java、Python和ScalaAPI,支持交互式的Python和Scala的shell
●以其RDD模型的强大表现能力,逐渐形成了一套自己的生态圈,提供了full-stack(全栈)的解决方案
●主要包括Spark内存中批处理,SparkSQL交互式查询,SparkStreaming流式计算,GraphX和MLib提供的常用图计算和机器学习算法
●Spark可以使用YARN作为它的集群管理器
●与Hadoop无缝衔接,读取HDFS、HBASE等一切Hadoop的数据
1.2.3.整体架构图
蓝色都是Spark自身的功能
1.2.4.核心概念
Spark提供多层分解概念,Spark组件将用户的应用程序分解为内部执行任务并提供执行容器,资源管理为spark组件提供资源管理和调度。
1.2.5.*典型应用
目前Spark主要应用在广告、报表、推荐系统等业务上。
在广告业务方面主要做应用分析、效果分析、定向优化等。
在推荐系统方面做排名、个性化推荐及热点点击分析等。
腾讯:
广点通是最早使用Spark的应用之一。
腾讯大数据精准推荐借助Spark快速迭代的优势,最终成功应用于广点通pCTR投放系统上,支持每天上百亿的请求量。
使用SparkSQL利用其快速查询以及内存表等优势,承担了日志数据的即席查询(即席查询是指那些用户在使用系统时,根据自己当时的需求定义的查询。
查询是用户在使用时临时生产的,系统无法预先优化这些查询,所以即席查询也是评估数据仓库的一个重要指标。
)工作。
在性能方面,普遍比Hive高2-10倍,如果使用内存表的功能,性能将会比Hive快100倍。
Yahoo:
将Spark用在AudienceExpansion中的应用,它是广告中寻找目标用户的一种方法:
首先广告者提供一些观看了广告并且购买产品的样本客户,据此进行学习,寻找更多可能转换的用户,对他们定向广告。
SparkSQL用于取代商业BI/OLAP工具,承担报表、仪表盘和交互式即席查询,同时与桌面BI工具对接。
淘宝:
淘宝技术团队使用Spark来解决多次迭代的机器学习算法、高计算复杂度的算法等。
将Spark运用于淘宝的推荐相关算法上。
同时还利用Graphx解决了许多生产问题,包括以下计算场景:
基于度分布的中枢节点发现、基于最大连通图的社区发现、基于三角形计数的关系衡量、基于随机游走的用户属性传播等。
优酷土豆:
视频推荐(图计算)、广告业务中广泛使用。
通过实践发现Spark性能比MR提升很多。
首先,交互查询响应快,性能比hadoop提高若干倍。
模拟广告投放计算效率高、延迟小。
机器学习、图计算等迭代计算,大大减少了网络传输、数据落地等。
极大的提高了计算性能。
1.2.6.Spark和informix、hive性能比较
Informix是IBM公司出品的关系数据库管理系统(RDBMS)家族。
作为一个集成解决方案,它被定位为作为IBM在线事务处理(OLTP)旗舰级数据服务系统。
1.2.7.Scala语言
学习Spark之前,先要学习一个语言scala,就是用它来编写的spark。
Storm也是由scala编写。
分布式开发中面临通信、远程调用、序列、反序列化、它都进行了封装,形成akka的架构,这样我们开发人员就可以已非常简洁的方式去开发分布式的应用,和单机没有区别。
Scala无缝集成Java,可以直接访问java的所有api,而且它用scala这个编译器把源文件编译成Java的class文件(即在JVM上运行的字节码)。
你可以从Scala中调用所有的Java类库,也同样可以从Java应用程序中调用Scala的代码。
它也可以访问现存的数之不尽的Java类库,这让(潜在地)迁移到Scala更加容易。
Java=>编译=>*.class=>JVM
Scala=>编译=>*.class=>JVM
扩展:
groovy、closurej(storm)都可以编译成.class,利用JVM。
Scala的编译器的作者就是Java编译器的作者。
1.2.8.安装Window下的ScalaShell
ScalaShell交互式的开发工具
scala-2.11.7.msiWindows安装包,在课前资料包中
安装完多了个目录,如下:
配置环境变量:
环境会自动加入,如果没有加入,手动配置
测试:
执行sacla命令,:
q退出
1.2.9.IDE第一个Scala例子
ScalaforEclipse
官网:
http:
//scala-ide.org/
解压scala-SDK-4.2.0-vfinal-2.11-win32.win32.x86_64.zip
创建ScalaProject,创建ScalaObject。
objectHello{
defmain(args:
Array[String]):
Unit={
print("helloworld!
");
}
}
1.3.Scala基础学习
1.3.1.方法定义
def方法名(参数:
类型[泛型]):
返回值={
表达式1;表达式2
表达式3
表达式4
}
注意:
一行有多个表达式,则加分号。
Unit相当于java中的void。
1.3.2.Option
Option类型在Scala中用来表示一个结果,它可能有值,也可能没有值,它有两个子类Some表示有值,None表示没有值,例如:
defdiv(a:
Int,b:
Int):
Option[Int]={
if(b!
=0)Some(a/b)elseNone
}
println(div(10,5))//返回Some
(2)
println(div(10,0))//返回None
它的好处是简化了调用者的处理。
Option提供了foreach方法和getOrElse
Option有一个方法getOrElse,它会在Option为None时采用默认值
valx1=div(10,5).getOrElse(0)
valx2=div(10,0).getOrElse(0)
println(x1)
println(x2)
注意,这样的好处是对于调用者来说,他们的处理方式是一致的,判断在getOrElse方法内部完成了,调用者不用判断。
再看Option的另一个方法foreach的使用,注意x2是None时根本不会进入其后的循环
valx1=div(10,5)
valx2=div(10,0)
x1.foreach{x=>println(x)}
x2.foreach{x=>println(x)}
1.3.3.变量、常量
vara=10;可以修改vara:
Int=10;不写类型,Scala会自动推演类型
valb=20;这个就无法修改
objecttest{
defmain(args:
Array[String]):
Unit={
println("helloworld!
");
vara=10;
valb=20;
println(a);
}
}
1.3.4.泛型
objecthelloworld{
defmain(args:
Array[String]):
Unit={
println("helloworld")
}
}
和java泛型不同的是,java是
1.3.5.表达式
objecthelloworld{
defmain(args:
Array[String]):
Unit={
vala=19
valc=if(a>10)"ok"else"nook"
println(c)
}
}
java中没有的,它使用表达式,通过判断去将结果放入c。
数组for/yield
valarray=Array(1,2,3,4,5)//创建数组并设置初始值
println(array(0))//获取第一个元素
for(x<-array){//打印数组的每个元素
println(x)
}
遍历数组并将每个元素+1,生成一个新数组
valarray=Array(1,2,3,4,5)//声明数组
valarray2=for(x<-array)yieldx+1
for(y<-array2){
println(y)
}
遍历数组,过滤掉小于等于2的元素
先过滤,再yield计算
valarray=Array(1,2,3,4,5)
valarray3=for(x<-arrayifx>2)yieldx
for(y<-array3){
println(y)
}
valarray4=for(x<-arrayifx>2)yieldx*10
for(y<-array4){
println(y)
}
遍历数组,只保留偶数的元素
importscala.collection.mutable.ArrayBuffer//必须引包
valarray=Array(1,2,3,4,5)
vararray4=ArrayBuffer[Int]()//动态数组
vari=0
for(x<-array){
if(i%2!
=0)array4.+=(x)//array4+=x
i+=1
}
for(y<-array4){
println(y)
}
注:
scala中方法名可以是“乱七八糟“的东西
1.3.6.特殊字符作为方法名
以问号等特殊符号作为方法名
objectstange{
defmain(args:
Array[String]):
Unit={
println(?
(1,2))//调用自定义方法
}
//以问号为方法名,必须指定参数类型,无需指定返回类型,scala会自动判断
def?
(a:
Int,b:
Int)={
a+b
}
}
如果方法内有多个表达式,最后一个表达式就是方法的返回值,不需要return关键字。
如果返回值已经能确定类型,就可以省略方法的返回值。
自定义以xxx作为方法名
objectstange{
defmain(args:
Array[String]):
Unit={
xxx//方法没有参数,可以省略掉调用时的括号()
}
defxxx()={
println("ok")
}
}
如果方法只有一个表达式,{}可以省略
1.3.7.Range对象
打印出1到10
for(x<-1to5)println(x)
for(x<-6.to(10))println(x)
1.3.8.字符串
StringContext
objectplay{
defmain(args:
Array[String]):
Unit={
vala=10
vals1="thevalueis:
"+a//传统方式
//s:
StringContext
vals2=s"thevalueis:
${a}"//类似jstl获取上面定义的常量
vals3=s"thevalueis:
$a"//缩写方式
println(s1)
println(s2)
println(s3)
}
}
变量还可以运算
valc=s"thevalueis:
${a/5}"
s是StringContext类的一个方法,看着很别扭,用起来很简洁。
避免转义字符,三个双引
valjson="{\"name\":
\"张三\"}"
valjson2="""{"name":
"张三"}"""
println(json2)
1.3.9.Object
Scala中没有静态的方法,变量,如果需要可以创建一个单例object达到类似目的。
objectSingleton{
valGlobalVal:
Int=100;
defGlobalFun(x:
Int,y:
Int)=x+y;
}
与类名一致的object称为该类的伴生对象,可以把伴生对象理解为该类的一个辅助对象,一些工具方法可以放入伴生对象中来定义。
1.3.10.匿名函数
匿名函数即对象,函数本质上就是对象,例如:
varfn=(x:
Int)=>println(x)
fn(x)
这个匿名函数其实是一个对象,它会被翻译成:
objectfnextendsFunction1[Int,Unit]{
defapply(x:
Int)=println("ok,"+x);
}
scala会自动加一个apply方法,而调用时会自动调用apply方法。
匿名函数在scala中广泛用到。
用法灵活,不会非得先定义方法,才能调用。
1.3.11.Class类
classPerson(valname:
String){}
声明非常简洁,它等价于java的代码,val就相当于声明的成员变量
publicclassPerson
{
privatefinalStringname;
publicStringname()
{
returnthis.name;
}
}
val只生成一个name,类似java中的get方法,因为只读无需生成set方法。
classPerson(varname:
String){}
println((newPerson("tony")).name)
如果是var就生成get、set方法但生成的方法也很怪异
publicclassPerson
{
privateStringname;
publicStringname()
{
returnthis.name;
}
publicvoidname_$eq(Stringx$1){this.name=x$1;}
}
1.3.12.CaseClass样例类
caseclassTeacher(varname:
String,age:
Int){
defteach(){
println(s"老师:
${name}正在讲课......")
}
defadd(age:
Int){
println("add"+age)
}
}
objectTeacher{
defmain(args:
Array[String]):
Unit={
valt1=Teacher("露娜",18)//创建对象省略new关键字
println(t1.name)
t1.name="李璐"
println(t1.name)
t1.teach()
valt2=Teacher("王莹",16)
t2add1//当方法是对象的属性时,括号可以去掉
}
}
样例类实现了序列化,同时默认实现了很多方法,例如toString、equals、hashCode等方法。
1.3.13.Extends继承
classPerson(valname:
String){
}
classStudent1(valname:
String,valage:
Int)extendsPerson(name){
}
classStudent2(overridevalname:
String,valage:
Int)
extendsPerson(name){
}
学生类student继承Person。
第一个student1的name实际引用的是父类的name属性。
student2的name是子类中的name属性。
还有一点要注意scala方法中如果参数是var类型,就不能进行override(父类方法已经实现,子类要重新实现就需要加一个override关键字),去覆盖它,这是scala语法的限制。
val可以。
caseclassTeacher(name:
String,age:
String)extendsPerson(name)
case类型默认两个参数的类型就是val所以可以省略不写。
如果要覆盖父类属性就必须写override。
caseclassTeacher(overridename:
String,age:
String)extendsPerson(name)
1.3.14.Trait接口加上抽象类
类似java中的接口加上抽象类,间接实现多继承,但还是有些差异
packagecom.scala
traitwork{
deftodo()//抽象方法,待子类实现
defdoing(){
println("doing....")
}
}
caseclasstask()extendswork{
deftodo(){
println("todosomething")
}
}
objecttest{
defmain(args:
Array[String]):
Unit={
//valo=work//抽象类不能实例化
valo=task();
o.todo
o.doing
}
}
1.4.*函数式编程学习
1.4.1.函数式编程的特点
函数式编程核心价值在于多核编程。
1)参数私有,没有线程安全问题,这样就为分布式高并发提供了支持
2)把函数做为参数
3)把函数的返回值作为参数
1.4.2.定义
在js中方法和函数比较模糊。
scala中的函数和方法不同,函数在scala中是一等公民。
格式:
(参数:
类型):
返回值类型=>{表达式;表达式...}
函数可以被赋值给其他变量或常量,可以作为参数传递,也可以作为返回值
objectTestFunction{
defadd(a:
Int,b:
Int)={a+b}//定义对象的方法
defmain(args:
Array[String]):
Unit={
valfnadd=(a:
Int,b:
Int)=>{a+b}//定义函数
println(fnadd(10,20))
}
}
1.4.3.函数编程的威力
任务:
已存在一个数字集合,按照奇偶数分成两个集合,下面是java的实现
java实现
List
list.add
(1);list.add
(2);list.add(3);list.add(4);list.add(5);
List
List
for(Integern:
list){
if(n%2==0){
a.add(n);
}else{
b.add(n);
}
}
scala实现
objectlist{
defmain(args:
Array[String]):
Unit={
//按奇偶数将集合划分为两个
valf2=(n:
Int)=>{n%2!
=0}//函数遇到奇数返回true,偶数返回false
valarray=Array(1,2,3,4,5).toList//初始化数组
println(array.partition(f2))//partition分区的意思
//还可以简写为
println(array.partition((n:
Int)=>{n%2!
=0}))
}
}
结果:
(List(1,3,5),List(2,4))
可以看到函数式编程的好处,让代码变的简单。
以前面向对象是做抽象、继承、封装、多态,以对象的观点去写我们的程序。
函数式编程把代码写在一个
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- scala