(十四)大数据学习之Scala语言

Scala编程语言

1.生态:

(1)scala编程语言

(2)Spark Core : Spark内核 ,最重要的一个部分。
(3)Spark SQL : 类似于 hive 和 pig。数据分析引擎。sql语句提交到spark集群中运行。
(4)Spark Streaming :类似于 storm,用于流式计算、实时计算。本质:一个离线计算。

Scala基础

一.Scala简介

1.scala是一个多范式的编程语言(支持多种方式的编程)
(1)使用面向对象编程:封装、继承、多态
(2)使用函数式编程:最大的特定

  • 优点:代码非常简洁
  • 缺点:可读性太差,尤其是隐式类、隐式函数、隐式参数

2.安装和配置scala
(1)基于JDK,先安装JDK
(2)scala:2.11.8(spark 2.1.0)

  • 配置环境变量:SCALA_HOME
  • %SCALA_HOME%\bin 配置到path中

下载地址:https://www.scala-lang.org
文档地址:https://www.scala-lang.org/api/2.11.8/#scala.math.package
(3)开发环境

  • REPL命令行
  • IDEA : 需要安装scala插件。

二.Scala中的数据类型和变量常量

1.注意一点:scala中所有的数据,都是对象。

  • 举例:1 java int 。在scala中,1 就是一个对象。

2.Scala常用数据类型:

Byte 8位有符号数字
Short 16位有符号数字
Int ...
Long
Float
Double
String
Char

(1)数值类型:Byte,Short,Int,Long,Float,Double

val a:Byte=10
a+10

res9:Int=20        //这里的res9是新生成变量的名字

val b:Short=20
a+b

注意:在Scala中,定义变量可以不指定类型,因为Scala会进行类型的自动推导
(2)字符类型和字符串类型:Char和String
对于字符串:在scala中可以进行插值操作:

scala>val s1="Hello World"
s1:String=Hello World

scala>"My Name is ${s1}"
res7:String=My Name is ${s1}

scala>s"My Name is ${s1}"
res8:String=My Name is Hello World

注意:前面有个s,相当于执行:“My Name is”+ s1

(3)Uint类型:相当于Java中的void类型

scala>val f = ()
f:Unit=()

scala>val f = {}
f:Uint=()

(4)Nothing类型:一般表示在执行过程中,产生了Exception

scala>def myfunction = throw new Exception("Some Error")
myfunction:Nothing

3.Scala变量的声明和使用
(1)使用val和var声明变量

scala>val answer=8*3+2

可在后续表达式中使用这些名称
(2)val:定义的值实际是一个常量,要声明其值可变的变量:var
注意:可以不用显示指定变量的类型,Scala会进行自动的类型推导

4.Scala的函数和方法的使用
(1)可以使用Scala的预定义函数

//例如求两个值的最大值
scala>import scala.math_    //需要导入相应的类
import scala.math_
scala>max(1,2)
res12:int=2

scala>var result:Int=max(1,2)   //也可以定义变量保存返回的值
result:Int=2

(2)也可以使用def关键字自定义函数
语法:

def 函数名称(参数列表:参数类型):返回值类型={
    //函数体
}

示例:

//求两个数字的和
scala>def sum(x:Int,y:Int)"Int=x+y
scala>sum(1,2)

scala>var d=sum(1,2)


//求某个数字的阶乘
scala>def myFactor(x:Int)Int={
    if(x<=1)
        1
    else
        x*myFactor(x-1)
}

scala>myFactor(5)

5.Scala的条件表达式:
(1)Scala的if/else语法结构和Java或C++一样。不过,在Scala中,if/else是表达式,有值,这个值就是跟在if或else之后的表达式的值。

6.Scala 的循环
(1)Scala拥有与Java和C++相同的while和do循环
(2)Scala中,可以使用for和foreach进行迭代
(3)使用for循环案例

var list = List("Mary","Tom","Mike")

println("*******for第一种写法********")
for(s<-list) println(s)

println("*******for第二种写法********")
for{
    s<-list
    if(s.length >3)
}println(s)

println("*******for第三种写法********")
for{s<-list if s.length<=3)println(s)

注意:

  • <- 表示Scala中的generator,即:提取符
  • 第三种写法是第二种写法的简写
    (4)在for循环中,还可以使用yield关键字来产生一个新的集合
var list = List("Mary","Tom","Mike")
println("*******for第四种写法********")
var newList=for{
    s<-list
    s1=s.toUpperCase
}yield(s1)

在上面的案例中,我们将list集合中的每个元素转换成了大写,并且使用yield关键字生成了一个新的集合。
(5)使用while循环:注意使用小括号,不是中括号

println("*******while*******")

var i=0
while(i<list.length){
    println(list(i))
}

(6)使用do ... while循环

println("*******while*******")

do{
    println(listO(i))
    i+=1
}while(i<list.length)

(7)使用foreach进行迭代

scala> val list =List("Mary","Tom","Mike")
list:List[String]=List(Marry,Tom,Mike)

scala>list.foreach(println)
Marry
Tom
Mike

注意:在上面的例子中,foreach接收了另一个函数(println)作为值

7.Scala函数的参数
(1)Scala中,有两种函数参数的求值策略

  • Call By Value:对函数实参求值,且仅求一次
  • Call By Name:函数实参每次在函数体内被用到时都会求值
//scala中函数参数的求值策略
//call by value
scala>def test1(x:Int,y:Int):Int=x+y
scala>test1(3+4,8)

//call by name
scala>def test2(x:=>Int,y:=>Int):Int = x+y

scala>test2(3+4,8)

分析上面的过程:

image.png

更复杂的例子:

image.png

(2)scala中的函数参数

  • 默认参数
  • 代名参数
  • 可变参数
image.png

8.Scala的lazy值

  • 当val被申明为lazy时,它的初始化将被推迟,直到我们首次对它取值
image.png

一个更复杂的例子

image.png

9.异常的处理:

  • Scala异常的工作机制和Java或者C++一样。直接使用throw关键字抛出异常
image.png

10.Scala中的数组
(1)scala数组的类型

  • 定长数组,使用关键字Array
  • 变长数组,使用关键字ArrayBuffer

定长数组

image.png

变长数组


image.png

(2)遍历数组

image.png

(3)Scala数组的常用操作:

image.png

(4)Scala的多维数组

  • 和Java一样,多维数组是通过数组的数组来实现的。
  • 也可以创建不规则的数组,每一行的长度各不相同。
image.png

11.映射
(1)映射就是Map集合,由一个(key,value)组成。

  • -> 操作符用来创建
//例如:
val scores = Map(“Alice” -> 10,”Bob” -> 3,”Cindy” -> 8)

(2)映射的类型分为:不可变Map和可变Map

image.png

(3)映射的操作

  • 获取映射中的值
image.png
  • 更新映射中的值(必须是可变Map)
image.png
  • 迭代映射
image.png

12.元组(Tuple)
(1)元组是不同类型的值的聚集。

//例如:
val t = (1, 3.14, "Fred") // 类型为Tuple3[Int, Double, java.lang.String],这里:Tuple是类型,3是表示元组中有三个元素。

(2)元组的访问和遍历:

image.png

注意:要遍历Tuple中的元素,需要首先生成对应的迭代器。不能直接使用for或者foreach。

二.scala语言的面向对象

1.面向对象的基本概念
把数据及对数据的操作方法放在一起,作为一个相互依存的整体——对象
面向对象的三大特征:

  • 封装
  • 继承
  • 多态

2.类的定义
(1)简单类和无参方法:

image.png

案例:注意没有class前面没有public关键字修饰。

image.png

(2)如果要开发main方法,需要将main方法定义在该类的伴生对象中,即:object对象中

image.png

3.属性的getter和setter方法
(1)当定义属性是private时候,scala会自动为其生成对应的get和set方法
private var stuName:String = "Tom"

  • get方法: stuName ----> s2.stuName() 由于stuName是方法的名字,所以可以加上一个括号
  • set方法: stuName_= ----> stuName_= 是方法的名字

(2)定义属性:private var money:Int = 1000 希望money只有get方法,没有set方法??

  • 办法:将其定义为常量private val money:Int = 1000

(3)private[this]的用法:该属性只属于该对象私有,就不会生成对应的set和get方法。如果这样,就不能直接调用,例如:s1.stuName ---> 错误

4.内部类(嵌套类)
(1)我们可以在一个类的内部在定义一个类,如下:我们在Student类中,再定义了一个Course类用于保存学生选修的课程。

image.png

(2)开发一个测试程序进行测试

image.png

5.类的构造器
类的构造器分为:主构造器、辅助构造器
(1)主构造器:和类的声明结合在一起,只能有一个主构造器
Student4(val stuName:String,val stuAge:Int)

  • 定义类的主构造器:两个参数
  • 声明了两个属性:stuName和stuAge 和对应的get和set方法
image.png

(2)辅助构造器:可以有多个辅助构造器,通过关键字this来实现

image.png

6.Scala中的Object对象
(1)Scala没有静态的修饰符,但Object对象下的成员都是静态的 ,若有同名的class,这其作为它的伴生类。在Object中一般可以为伴生类做一些初始化等操作。
下面是Java中的静态块的例子。在这个例子中,我们对JDBC进行了初始化。

image.png

而Scala中的Object就相当于Java中静态块。
(2)Object对象的应用

  • 单例对象
image.png
  • 使用应用程序对象,可以省略main方法;需要从父类App继承
image.png

7.Scala中的apply方法
(1)遇到如下形式的表达式时,apply方法就会被调用:

Object(参数1,参数2,......,参数N)

通常,这样一个apply方法返回的是伴生类的对象;其作用是为了省略new关键字
(2)Object的apply方法举例:

image.png

8.Scala中的继承
Scala和Java一样,使用extends关键字扩展类。
(1) 案例一:Employee类继承Person类

image.png

(2)案例二:在子类中重写父类的方法

image.png

(3)案例三:使用匿名子类

image.png

(4)案例四:使用抽象类。抽象类中包含抽象方法,抽象类只能用来继承。

image.png

(5)案例五:使用抽象字段。抽象字段就是一个没有初始值的字段

image.png

9.Scala中的tarit(特质)

  • trait就是抽象类。trait跟抽象类最大的区别:trait支持多重继承
image.png

10.包的使用
(1)scala包和java中的包或者c++中的命名空间的目的是相同的,管理大型程序中的名称。

image.png

(2)Scala中包的定义和使用:

  • 包的定义
image.png
  • 包的引入:Scala中依然使用import作为引用包的关键字,例如
image.png
  • 而且Scala中的import可以写在任意地方
image.png

11.包对象
(1)包可以包含类、对象和特质,但不能包含函数或者变量的定义。很不幸,这是Java虚拟机的局限。
(2)把工具函数或者常量添加到包而不是某个Utils对象,这是更加合理的做法。Scala中,包对象的出现正是为了解决这个局限。
(3)Scala中的包对象:常量,变量,方法,类,对象,trait(特质)

image.png

12.Scala中的文件访问
(1)读取行

image.png

(2)读取字符

image.png
  • 其实这里的source就指向了这个文件中的每个字符

(3)从URL或者其他源读取,注意指定字符集UTF-8

image.png

(4)读取二进制文件:Scala中并不支持直接读取二进制,但可以通过调用Java的InputStream来进行读入。

image.png

(5)写入文本文件

image.png

三.scala语言的函数式编程

1.Scala中的函数
在Scala中,函数是“头等公民”,就和数字一样。可以在变量中存放函数,即:将函数作为变量的值(值函数)

image.png

2.匿名函数

image.png

3.带函数参数的函数,即:高阶函数
(1)示例1:

  • 首先,定义一个最普通的函数
image.png
  • 再定义一个高阶函数
image.png
  • 分析这个高阶函数调用的过程


    image.png

(2)示例2:

image.png
  • 在这个例子中,首先定义了一个普通的函数mytest,然后定义了一个高阶函数myFunction;myFunction接收三个参数:第一个f是一个函数参数,第二个是x,第三个是y。而f是一个函数参数,本身接收两个Int的参数,返回一个Int的值。

4.闭包
(1)就是函数的嵌套,即:在一个函数定义中,包含另外一个函数的定义;并且在内函数中可以访问外函数中的变量。

image.png

(2)测试上面的函数:

image.png

5.柯里化:Currying
(1)柯里化函数(Curried Function)是把具有多个参数的函数转换为一条函数链,每个节点上是单一参数。

image.png

(2)一个简单的例子

image.png

6.高阶函数示例
(1)一些有用的高阶函数


image.png

(2)示例1:

image.png

(3)示例2

image.png

(4)示例3

image.png

(5)示例4

image.png

(6)示例5

image.png
  • 在这个例子中,可以被2整除的被分到一个分区;不能被2整除的被分到另一个分区。
    (7)示例6
image.png

(8)示例7

image.png

(9)示例8

image.png

在这个例子中,分为两步:

  • 将(1,2,3)和(4,5,6)这两个集合合并成一个集合
  • 然后再对每个元素乘以2

四.Scala中的集合

1.可变集合和不可变集合
(1)可变集合
(2)不可变集合:

  • 集合从不改变,因此可以安全地共享其引用。
  • 甚至是在一个多线程的应用程序当中也没问题。
image.png

(3)集合的操作:

image.png

2.列表
(1)不可变列表(List)

image.png
  • 不可变列表的相关操作:
image.png

(2)可变列表(LinkedList):scala.collection.mutable

image.png

3.序列
常用的序列有:Vector和Range
(1)Vector是ArrayBuffer的不可变版本,是一个带下标的序列

image.png

(2)Range表示一个整数序列

image.png

4.集(Set)和集的操作
(1)集Set是不重复元素的集合
(2)和列表不同,集并不保留元素插入的顺序。默认以Hash集实现
(3)示例1:创建集

image.png

(4)示例2:集的操作

image.png

5、模式匹配
(1)Scala有一个强大的模式匹配机制,可以应用在很多场合:

  • switch语句
  • 类型检查

(2)Scala还提供了样本类(case class),对模式匹配进行了优化

(3)模式匹配示例:

  • 更好的switch
image.png
  • Scala的守卫
image.png
  • 模式匹配中的变量
image.png
  • 类型模式
image.png
  • 匹配数组和列表

数组:

image.png

列表:

image.png

6.样本类:
(1)简单的来说,Scala的case class就是在普通的类定义前加case这个关键字,然后你可以对这些类来模式匹配。

case class带来的最大的好处是它们支持模式识别。

(2)首先,回顾一下前面的模式匹配:

image.png

(3)其次,如果我们想判断一个对象是否是某个类的对象,跟Java一样可以使用isInstanceOf

image.png

(4)下面这个好像有点问题

image.png

(5)最后,在Scala中有一种更简单的方式来判断,就是case class

image.png

注意:需要在class前面使用case关键字。

五.Scala语言的高级特性

1.什么是泛型类

  • 和Java或者C++一样,类和特质可以带类型参数。在Scala中,使用方括号来定义类型参数
image.png

测试程序:

image.png

2.什么是泛型函数

  • 函数和方法也可以带类型参数。和泛型类一样,我们需要把类型参数放在方法名之后。
  • 注意:这里的ClassTag是必须的,表示运行时的一些信息,比如类型。
image.png

3.Upper Bounds 与 Lower Bounds
(1)类型的上界和下界,是用来定义类型变量的范围。它们的含义如下:

  • S <: T
    这是类型上界的定义。也就是S必须是类型T的子类(或本身,自己也可以认为是自己的子类。
  • U >: T
    这是类型下界的定义。也就是U必须是类型T的父类(或本身,自己也可以认为是自己的父类)。

(2)一个简单的例子:

image.png

(3)一个复杂一点的例子(上界):

image.png

(4)再来看一个例子:

image.png

4.视图界定(View bounds)
(1)它比 <: 适用的范围更广,除了所有的子类型,还允许隐式转换过去的类型。用 <% 表示。尽量使用视图界定,来取代泛型的上界,因为适用的范围更加广泛。
示例:

  • 上面写过的一个列子。这里由于T的上界是String,当我们传递100和200的时候,就会出现类型不匹配。
image.png
  • 但是100和200是可以转成字符串的,所以我们可以使用视图界定让addTwoString方法接收更广泛的数据类型,即:字符串及其子类、可以转换成字符串的类型。
    注意:使用的是 <%
image.png
  • 但实际运行的时候,会出现错误:
image.png

这是因为:Scala并没有定义如何将Int转换成String的规则,所以要使用视图界定,我们就必须创建转换的规则。

  • 创建转换规则
image.png
  • 运行成功
image.png

5.协变和逆变
(1)协变:

  • Scala的类或特征的范型定义中,如果在类型参数前面加入+符号,就可以使类或特征变为协变了。
image.png

(2)逆变:

  • 在类或特征的定义中,在类型参数之前加上一个-符号,就可定义逆变范型类和特征了。
image.png

总结一下:

  • Scala的协变:泛型变量的值可以是本身类型或者其子类的类型
  • Scala的逆变:泛型变量的值可以是本身类型或者其父类的类型

6、隐式转换函数
(1)所谓隐式转换函数指的是以implicit关键字申明的带有单个参数的函数。

  • 前面讲视图界定时候的一个例子:
image.png
  • 再举一个例子:我们把Fruit对象转换成了Monkey对象
image.png

7、隐式参数

  • 使用implicit申明的函数参数叫做隐式参数。我们也可以使用隐式参数实现隐式的转换
image.png

8、隐式类

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

推荐阅读更多精彩内容