scala语言课程设计
文章目录
-
- scala语言课程设计
- 一、课前准备
- 二、课堂主题
- 三、课堂目标
- 四、知识要点
-
- 1. scala简介
- 2. 为什么要使用scala
- 3. 开发环境安装
- 4. scala的REPL交互式解释器
- 5. scala中声明变量
- 6. scala中数据类型
- 7. scala中的条件表达式
- 8. scala中的块表达式
- 9. 循环
- 10. 方法和函数
- 11. 数组
- 12. 元组
- 13. 映射Map
- 14. Set集合
- 15. 列表 List
- 16. 函数式编程
- 17. 高阶函数
- 18. scala面向对象编程之类
- 19.scala面向对象编程之对象
- 20. scala面向对象编程之继承
- 21. scala面向对象编程之trait特质
- 22. 模式匹配和样例类
- 23. 异常处理
- 24. 提取器(Extractor)
- 25. 泛型
- 26. 上下界
- 27. 协变、逆变、非变
- 28. 隐式转换和隐式参数
- 五、拓展点、未来计划、行业趋势
- 六、总结
- 七、作业
- 八、互动问答
- 九、题库 - 本堂课知识点
一、课前准备
- 1、安装好1.8 JDK环境
二、课堂主题
本堂课主要围绕scala 基础语法 进行讲解。主要包括以下几个方面
- scala语言简介
- scala开发环境搭建
- scala的基础语法
- scala的集合操作
三、课堂目标
- 搭建scala开发环境
- 掌握scala基本语法结构(变量、表达式、if、循环、方法、函数…)
- 掌握scala集合使用(数组、元组、List、Set、Map…)
四、知识要点
1. scala简介
- scala是运行在 JVM 上的多范式编程语言,同时支持面向对象和面向函数编程
- 早期scala刚出现的时候,并没有怎么引起重视,随着Spark和Kafka这样基于scala的大数据框架的兴起,scala逐步进入大数据开发者的眼帘。scala的主要优势是它的表达性。
- 官网地址
- http://www.scala-lang.org
2. 为什么要使用scala
- 开发大数据应用程序(Spark程序、Flink程序)
- 表达能力强,一行代码抵得上Java多行,开发速度快
- 兼容Java,可以访问庞大的Java类库
3. 开发环境安装
-
学习如何编写scala代码之前,需要先安装scala编译器以及开发工具
-
Java程序编译执行流程
-
Scala程序编译执行流程
-
-
scala程序运行需要依赖于Java类库,必须要有**Java运行环境**,scala才能正确执行
- 要编译运行scala程序需要
- jdk ( jvm )
- scala编译器(scala SDK)
- 要编译运行scala程序需要
3.1 安装JDK
安装JDK 1.8 64位版本,并配置好环境变量
3.2 安装scala SDK
scala SDK是scala语言的编译器,要开发scala程序,必须要先安装SDK
-
访问地址
- https://www.scala-lang.org/download/2.11.8.html
- 下载安装包
- scala-2.11.8.zip
- 下载安装包
- https://www.scala-lang.org/download/2.11.8.html
-
在window在配置scala SDK,并配置好环境变量
3.3 安装IDEA的scala插件
IDEA默认是不支持scala程序开发,所以需要来安装scala插件来支持scala语言。
- 1、查看IDEA版本
-
2、到IDEA官网下载对应版本的IDEA scala插件
请务必下载IDEA版本一致的scala插件 scala-intellij-bin-2017.2.2.zip
-
3、点击File ,再点击Settings
-
4、添加scala插件后,重启IDEA
4. scala的REPL交互式解释器
-
Scala提供的最重要的一个工具是交互模式(REPL)。REPL是一个交互式解释器,可以即时编译、运行代码并返回结果,方便前期做学习和测试
-
REPL
- R(read)、E(evaluate) 、P(print)、L(loop)
-
要启动scala解释器,只需要以下几步:
- 按住
windows键 + r
- 输入
scala
即可
- 按住
-
退出scala解释器
- 使用 :quit 就可以了
5. scala中声明变量
- 1、语法格式
val/var 变量名称:变量类型 = 初始值
-
其中
val
定义的是不可重新赋值的变量(值不可修改)var
定义的是可重新赋值的变量(值可以修改)
-
ps
- scala中声明变量是变量名称在前,变量类型在后,跟java是正好相反
- scala的语句最后不需要添加分号
-
2、演示
#使用val声明变量,相当于java中的final修饰,不能在指向其他的数据了 val a:Int = 10 #使用var声明变量,后期可以被修改重新赋值 var b:Int = 20 b=100 #scala中的变量的类型可以显式的声明,也可以不声明,如果不显式的声明这会根据变量的值来推断出来变量的类型(scala支持类型推断) val c = 20
-
3、惰性变量
- Scala中使用==关键字lazy==来定义惰性变量,实现延迟加载(懒加载)。
- 惰性变量只能是不可变变量,并且只有在调用惰性变量时,才会去实例化这个变量。
- 语法格式
lazy val 变量名 = 表达式
6. scala中数据类型
- scala中的类型绝大多数和Java一样
- 数据类型
基础类型 | 类型说明 |
---|---|
Byte | 8位带符号整数 |
Short | 16位带符号整数 |
Int | 32位带符号整数 |
Long | 64位带符号整数 |
Char | 16位无符号Unicode字符 |
String | Char类型的序列(字符串) |
Float | 32位单精度浮点数 |
Double | 64位双精度浮点数 |
Boolean | true或false |
- 注意下 scala类型与Java的区别
1. scala中所有的类型都使用大写字母开头
2. 整形使用Int而不是Integer
3. scala中定义变量可以不写类型,让scala编译器自动推断
- scala类型层次结构
类型 | 说明 |
---|---|
Any | 所有类型的父类,,它有两个子类AnyRef与AnyVal |
AnyVal | 所有数值类型的父类 |
AnyRef | 所有对象类型(引用类型)的父类 |
Unit | 表示空,Unit是AnyVal的子类,它只有一个的实例(),它类似于Java中的void,但scala要比Java更加面向对象 |
Null | Null是AnyRef的子类,也就是说它是所有引用类型的子类。它的实例是null, 可以将null赋值给任何对象类型 |
Nothing | 所有类型的子类不能直接创建该类型实例,某个方法抛出异常时,返回的就是Nothing类型,因为Nothing是所有类的子类,那么它可以赋值为任何类型 |
7. scala中的条件表达式
- 条件表达式就是if表达式,if表达式可以根据给定的条件是否满足,根据条件的结果(真或假)决定执行对应的操作。scala条件表达式的语法和Java一样。
//定义变量x
scala> val x =1
x: Int = 1
//if表达式
scala> val y =if(x>0) 1 else -1
y: Int = 1
//支持混合类型表达式
scala> val z=if(x>1) 1 else "error"
z: Any = error
//缺失else 相当于 if(x>2) 1 else ()
scala> val m=if(x>2) 1
m: AnyVal = ()
//scala中有个Unit类,用作不返回任何结果的方法的结果类型,相当于Java中的void,Unit只有一个实例值,写成()
scala> val n=if(x>2) 1 else ()
n: AnyVal = ()
//if(xx) else if(xx) else
scala> val k=if(x<0) -1 else if (x==0) 0 else 1
k: Int = 1
8. scala中的块表达式
- 定义变量时用 {} 包含一系列表达式,其中块的最后一个表达式的值就是块的值。
val x=0
val result={
val y=x+10
val z=y+"-hello"
val m=z+"-kaikeba"
"over"
}
//result的值就是块表达式的结果
//后期一个方法的返回值不需要加上return,把要返回的结果放在方法的最后一行就可以了
- 在scala解释器中先输入 :paste ,然后写多行代码, 之后按=ctrl+d结束输入
9. 循环
在scala中,可以使用for和while,但一般推荐使用for表达式,因为for表达式语法更简洁
9.1 for循环
-
1、语法结构
for (i <- 表达式/数组/集合){ //表达式 }
-
2、演示
- 简单的for循环
//简单的for循环 scala> val nums= 1 to 10 nums: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) scala> for(i <- nums) println(i) 1 2 3 4 5 6 7 8 9 10
- 双重for循环
//双重for循环 scala> for(i <- 1 to 3; j <- 1 to 3) println(i*10+j) 11 12 13 21 22 23 31 32 33 //双重for循环打印99乘法表 for(i <- 1 to 9; j <- 1 to i){ print(i+"*"+j+"="+i*j+"\t") if(i==j){ println() } } 1*1=1 2*1=2 2*2=4 3*1=3 3*2=6 3*3=9 4*1=4 4*2=8 4*3=12 4*4=16 5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
- 守卫
- 在for表达式中可以添加if判断语句,这个if判断就称为守卫
//语法结构 for(i <- 表达式/数组/集合 if 表达式) { // 表达式 } scala> for(i <- 1 to 10 if i >5) println(i) 6 7 8 9 10
- for推导式
- 在for循环体中,可以使用yield表达式构建出一个集合,我们把使用yield的for表达式称之为推导式
// for推导式:for表达式中以yield开始,该for表达式会构建出一个集合 val v = for(i <- 1 to 5) yield i * 10
9.2 while循环
- scala中while循环和Java中是一致的
- 语法结构
while(返回值为布尔类型的表达式){
//表达式
}
- 演示
scala> var x = 10
x: Int = 10
scala> while(x >5){
| println(x)
| x -= 1
| }
10
9
8
7
6
10. 方法和函数
10.1 方法
- 语法
def methodName (参数名:参数类型, 参数名:参数类型) : [return type] = {
// 方法体:一系列的代码
}
-
说明
- 参数列表的参数类型不能省略 - 返回值类型可以省略,由scala编译器自动推断 - 返回值可以不写return,默认就是{}块表达式的值
-
演示
scala> def add(a:Int,b:Int) = a+b add: (a: Int, b: Int)Int scala> add(1,2) res8: Int = 3 scala>
-
注意
- 如果定义递归方法,不能省略返回值类型
- 示例:
- 定义递归方法(求阶乘)
- 10 * 9 * 8 * 7 * 6 * … * 1
- 定义递归方法(求阶乘)
scala> def m1(x:Int)={ | if(x==1) 1 | else x * m1(x-1) | } <console>:14: error: recursive method m1 needs result type else x * m1(x-1) ^ scala> def m1(x:Int):Int={ | if(x==1) 1 | else x * m1(x-1) | } m1: (x: Int)Int scala> m1(10) res9: Int = 3628800
-
方法的参数
-
1、默认参数
-
在定义方法时可以给参数定义一个默认值。
-
示例
//1. 定义一个计算两个值相加的方法,这两个值默认为0 //2. 调用该方法 scala> def add(x:Int = 0, y:Int = 0) = x + y add: (x: Int, y: Int)Int scala> add(10) res14: Int = 10 scala> add(10,20) res15: Int = 30
-
-
2、带名参数
-
在调用方法时,可以指定参数的名称来进行调用。
-
示例
scala> def add(x:Int = 0, y:Int = 0) = x + y add: (x: Int, y: Int)Int scala> add(x=1) res16: Int = 1
-
-
3、变长参数
-
如果方法的参数是不固定的,可以定义一个方法的参数是变长参数。
-
语法格式:
def 方法名(参数名:参数类型*):返回值类型 = { 方法体 } //在参数类型后面加一个*号,表示参数可以是0个或者多个
-
示例
scala> def add(num:Int*) = num.sum add: (num: Int*)Int scala> add(1,2,3,4,5) res17: Int = 15
-
-
10.2 函数
- scala支持函数式编程,将来编写Spark/Flink程序中,会大量使用到函数
- 语法
val 函数变量名 = (参数名:参数类型, 参数名:参数类型....) => 函数体
- 注意
- 函数是一个对象(变量)
- 类似于方法,函数也有输入参数和返回值
- 函数定义不需要使用def定义
- 无需指定返回值类型
- 演示
scala> val add = (x:Int, y:Int) => x + y
add: (Int, Int) => Int = <function2>
scala> add(1,2)
res3: Int = 3
//一个函数没有赋予一个变量,则称为匿名函数,
//后期再实际开发代码的时候,基本上都是使用匿名函数
(x:Int,y:Int)=>x+y
10.3 方法和函数的区别
- 方法是隶属于类或者对象的,在运行时,它是加载到JVM的方法区中
- 可以将函数对象赋值给一个变量,在运行时,它是加载到JVM的堆内存中
- 函数是一个对象,继承自FunctionN,函数对象有apply,curried,toString,tupled这些方法,而方法则没有
10.4 方法转换为函数
-
有时候需要将方法转换为函数,作为变量传递,就需要将方法转换为函数
-
使用
_
即可将方法转换为函数 -
示例
scala> def add(x:Int,y:Int)=x+y add: (x: Int, y: Int)Int scala> val a = add _ a: (Int, Int) => Int = <function2>
11. 数组
- scala中数组的概念是和Java类似,可以用数组来存放一组数据
- scala中,有两种数组,一种是定长数组,另一种是变长数组
11.1 定长数组
-
定长数组指的是数组的长度是不允许改变的
-
数组的元素是可以改变的
-
语法
// 通过指定长度定义数组 val/var 变量名 = new Array[元素类型](数组长度) // 用元素直接初始化数组 val/var 变量名 = Array(元素1, 元素2, 元素3...)
-
注意
在scala中,数组的泛型使用[]来指定 使用()来获取元素
-
演示
scala> val a=new Array[Int](10) a: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0) scala> a(0) res19: Int = 0 scala> a(0)=10 scala> a res21: Array[Int] = Array(10, 0, 0, 0, 0, 0, 0, 0, 0, 0) // scala> val b =Array("hadoop","spark","hive") b: Array[String] = Array(hadoop, spark, hive) scala> b(0) res24: String = hadoop scala> b.length res25: Int = 3
11.2 变长数组
-
变长数组指的是数组的长度是可变的,可以往数组中添加、删除元素
-
创建变长数组,需要提前导入ArrayBuffer类
import scala.collection.mutable.ArrayBuffer
-
语法
- 创建空的ArrayBuffer变长数组
val/var a = ArrayBuffer[元素类型]()
- 创建带有初始元素的ArrayBuffer
val/var a = ArrayBuffer(元素1,元素2,元素3....)
-
演示
//导入ArrayBuffer类型 scala> import scala.collection.mutable.ArrayBuffer import scala.collection.mutable.ArrayBuffer //定义一个长度为0的整型变长数组 scala> val a=ArrayBuffer[Int]() a: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer() //定义一个有初始元素的变长数组 scala> val b = ArrayBuffer("hadoop", "storm", "spark") b: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer(hadoop, storm, spark)
-
变长数组的增删改操作
- 使用
+=
添加元素 - 使用
-=
删除元素 - 使用
++=
追加一个数组到变长数组
- 使用
-
示例
// 定义变长数组 scala> val a = ArrayBuffer("hadoop", "spark", "flink") a: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer(hadoop, spark, flink) // 追加一个元素 scala> a += "flume" res10: a.type = ArrayBuffer(hadoop, spark, flink, flume) // 删除一个元素 scala> a -= "hadoop" res11: a.type = ArrayBuffer(spark, flink, flume) // 追加一个数组 scala> a ++= Array("hive", "sqoop") res12: a.type = ArrayBuffer(spark, flink, flume, hive, sqoop)
11.3 遍历数组
-
可以使用以下两种方式来遍历数组:
- 使用for表达式 直接遍历数组中的元素
- 使用 索引 遍历数组中的元素
-
示例
scala> for(i <- a)println(i)
hadoop
hive
flume
spark
scala> for(i <- 0 to a.length -1 )println(a(i))
hadoop
hive
flume
spark
scala> for(i <- 0 until a.length) println(a(i))
hadoop
hive
flume
spark
//0 until n ——生成一系列的数字,包含0,不包含n
//0 to n ——包含0,也包含n
11.4 数组常用操作
- scala中的数组封装了丰富的计算操作,将来在对数据处理的时候,不需要我们自己再重新实现。
- 求和——sum方法
- 求最大值——max方法
- 求最小值——min方法
- 排序——sorted方法
- 示例
scala> val array=Array(1,3,4,2,5)
array: Array[Int] = Array(1, 3, 4, 2, 5)
//求和
scala> array.sum
res10: Int = 15
//求最大值
scala> array.max
res11: Int = 5
//求最小值
scala> array.min
res12: Int = 1
//升序
scala> array.sorted
res13: Array[Int] = Array(1, 2, 3, 4, 5)
//降序 reverse 反转
scala> array.sorted.reverse
res14: Array[Int] = Array(5, 4, 3, 2, 1)
12. 元组
- 元组可以用来包含一组不同类型的值。例如:姓名,年龄,性别,出生年月。元组的元素是不可变 的。
12.1 定义元组
-
语法
-
使用括号来定义元组
val/var 元组变量名称 = (元素1, 元素2, 元素3....)
-
使用箭头来定义元素(元组只有两个元素)
val/var 元组 = 元素1->元素2
-