6

2小时速学大数据编程语言 Scala 秘籍

 2 years ago
source link: https://blog.51cto.com/u_7932852/5070493
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

作者:幻好

Scala 系列:

 ​2小时速学大数据编程语言 Scala 秘籍​

 ​大数据编程语言 Scala 进阶篇​

在深入学习大数据框架 Spark 和 Fink 时,为了能够理解其底层源码,就需要学会 Scala 编程语言。Scala 的设计源于 Java,但又“高于”Java,是基于 Java 之上增加了一层封装,让程序员可以通过​函数式编程​的方式来开发程序。所以如果学习之前,有 Java 或其他编程语言的基础,2小时学会 Scala 没什么问题。

本文将对 Scala 的安装以及基础语法要点进行总结,以实例的方式帮助快速学会 Scala 语法,能够帮助你读懂相关开源框架的程序逻辑。

Scala介绍

Scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性。

Scala 运行在 Java 虚拟机上,并兼容现有的 Java 程序。Scala 源代码被编译成 Java 字节码,所以它可以运行于 JVM 之上,并可以调用现有的 Java 类库。

如果在学习 scala 之前学过 java 基础,上手 scala 会更快。

面向对象性​:Scala是一种纯面向对象的语言,每个值都是对象,对象的数据类型以及行为由类和特质描述。

类抽象机制的扩展主要通过子类的继承或者灵活的混入机制。

函数式编程​:Scala 是一种函数式语言,函数也能当值来使用,提供轻量级的语法用以定义匿名函数,支持高阶函数,允许嵌套多层函数,并支持柯里化。

安装Scala

由于Scala是基于JVM虚拟机运行的,所以在安装Scala之前,需要提前安装好JDK。

目前Scala有2.0和3.0的版本,使用的较多的版本是2.0版本,以2.13版本为例下载安装。

官网下载链接:​ ​https://www.scala-lang.org/download/scala2.html​

找到需要的环境版本安装包,安装Scala。

Windows中安装

系统win10,下载好 ​​scala-2.13.8.zip​​ 安装文件到本地后解压,然后进入系统属性中,配置环境变量:

  • 首先增加一个变量​​SCALA_HOME​​​ ,并指定到解压目录(bin目录的上级)下​​D:\Soft_install\scala\scala-2.13.8​
  • 在 Path 变量中,增加 Scala 的 bin 路径:​​%SCALA_HOME%\bin​
  • 在 CLASSPATH 系统变量中,增加 Scala 的 bin 路径:​​;%SCALA_HOME%\bin​
  • 以上系统变量设置好后,然后进行安装的验证,打开命令窗口,输入:scala
  • 会打印系统安装的Scala版本,并进入 Scala 的命令行环境(与 Python 相似)

以上安装并验证完成后,说明 Scala 已经安装成功,可以开始后续开发工作。

Scala基础语法

对于有编程语法基础尤其是 Java 的人来说,上手 scala 是非常快的。

首先,先来一段代码示例:

// 指定文件包
package demo01
// import 引入其他包对象或类, HashMap => JavaHashMap 为重命名成员
import java.util.{HashMap => JavaHashMap}
// 引入 java.util 中的所有成员
import java.util._


/**
* object 声明 HelloWorld 为一个实力对象
* def 修饰 main 方法,可以直接执行
* println 打印字符串 "Hello, world!"
*/
object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello, world!")
}
}

Sacala 源码文件以 ​​.scala​​​ 后缀,如果需要执行编写的 Scala 程序,需要先将写的源码编译成字节码文件 ​​.class​​ ,然后通过 JVM 虚拟机执行。

语法中需要注意和理解的点:

  • 所有类名首字母需要大写,方法名都要小写,文件程序名与类名或程序名一致。
  • Scala 程序默认执行,都是从main 方法开始执行。
  • Scala 程序能够直接引用 Java 库使用。

对于初学者来说,需要理解 Scala 中的一些语法概念:

表示抽象的对象,可以理解描述对象的属性行为的规范

表示类的示例化,类的具体示例,占用内存空间

方法与函数基本相同,用来描述某一通用的过程或流程

Scala 作为面向对象的语言,其数据类型和 Java 的有者很大的相似性,主要类型如下:

8位有符号补码整数。数值区间为 -128 到 127

Short

16位有符号补码整数。数值区间为 -32768 到 32767

32位有符号补码整数。数值区间为 -2147483648 到 2147483647

64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807

Float

32 位, IEEE 754 标准的单精度浮点数

Double

64 位 IEEE 754 标准的双精度浮点数

16位无符号Unicode字符, 区间值为 U+0000 到 U+FFFF

String

字符串,使用双引符号 ​​"​​​ 修饰,多行字符串用符号 ​​"""​​ 修饰

Boolean

true或false

表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。

null 或空引用

Nothing

Nothing类型在Scala的类层级的最底端,它是任何其他类型的子类型。

Any是所有其他类的超类

AnyRef

AnyRef类是Scala里所有引用类(reference class)的基类

Scala 中的数据类型一般通过声明指定: ​​var str : String = "ok"​​​ ,通过符号 ​​:​​​ 去指定数据类型;或者直接赋值,就能通过赋值的类型就能指定其数据类型: ​​var str = "ok"​​ 。

在 Scala 中,字符串的类型实际上是 Java 中的 ​​java.lang.String​​​ 类,Scala 本身没有 ​​String​​ 类,所以如果对于会 Java 语法的人,可以简单略过本节。

由于 Scala 直接使用的 Java 中的 ​​String​​​ 类,所以其是不可变对象,具体可参考官方API文档:​ ​https://docs.oracle.com/javase/8/docs/api/java/lang/String.html​

Scala 中提供的用来存放固定大小的数组的同类型元素,具体使用案例如下:

// 定义一个数组
var arr1 : Array[String] = new Array[String](3);
var arr2 = new Array[String](3);
var arr3 = Array("a", "b", "c");
// 数组访问赋值
arr1(0) = "x";
println(arr1(0))
// 定义多维数组 ofDim 指定数组的长度
val arrMultia = Array.ofDim[Int](2 2)
// 合并数组
arr2 = concat( arr1, arr3)

Scala 中的变量分为可变和不可变,变量用于引用内存地址,创建后占用一定的内存空间。

可变变量主要用 ​​var​​​ 修饰符修饰:​​var x = "temp"​

不可变量(常量)主要用 ​​val​​​ 修饰符修饰:​​val x = 1​

object BaseExample {
def main(args : Array[String]) : Unit = {

// 变量的声明
var change : String = "可变量" // 变量初始化后,可以再次赋值
val noChange : String = "不可变量" // 常量初始化后,再次赋值会编译报错

// 变量声明可以不指定类型,但是必须赋初始值,否则编译报错
var changes = "可变量"
val noChanges = "不可变量"

// 同时声明多个变量
var x,y = 20 // 同时给x,y都赋值20

}
}

变量语法中,需要​注意和理解​的点:

  • 在声明变量和常量时,不一定要指定数据类型,但是一定要赋值初始值,其类型能够通过赋值推出,所以这块需要注意一下。
  • 在开发中,如果有些变量不会被修改,建议多使用常量修饰,可以防止被错误修改导致程序错误。

Scala 中的运算符基本上和其他编程语言一样,如果有其他语言基础,可以直接跳过这一节。

Scala 中的运算符主要有:

  • 算术运算符
  • 关系运算符

>=

<=

  • 逻辑运算符

按位与运算符

按位或运算符

按位异或运算符

按位取反运算符

<<

左移动运算符

>>

右移动运算符

>>>

无符号右移

  • 赋值运算符

简单的赋值运算,指定右边操作数赋值给左边的操作数。

相加后再赋值,将左右两边的操作数相加后再赋值给左边的操作数。

相减后再赋值,将左右两边的操作数相减后再赋值给左边的操作数。

相乘后再赋值,将左右两边的操作数相乘后再赋值给左边的操作数。

相除后再赋值,将左右两边的操作数相除后再赋值给左边的操作数。

求余后再赋值,将左右两边的操作数求余后再赋值给左边的操作数。

<<=

按位左移后再赋值

>>=

按位右移后再赋值

按位与运算后赋值

按位异或运算符后再赋值

按位或运算后再赋值

Scala 中的条件判断使用 ​​if...else​​​ 语句,根据条件的 ​​true​​​ 或 ​​fasle​​ 进行判断下一步执行的代码。

主要掌握以下语法:

if(条件 1){
// 如果条件 1 为 true 则执行
}else if(条件 2){
// 如果条件 2 为 true 则执行
}else if(条件 3){
// 如果条件 3 为 true 则执行
}else {
// 如果以上条件都为 false 则执行
}

与 Java 中的 ​​if​​ 语句基本相同,会 Java 的同学可以直接跳过。

Scala 主要提供了 ​​for​​​ 循环 、​​while​​​ 循环、​​do...while​​​ 循环语句,循环中的中断只有在 2.8+ 版本以上,才支持了 ​​break​​ 语句,需要注意下。

for循环

for 循环主要掌握以下几个示例即可。

语法示例:

/*
* for 循环
*/
// 通用 for 循环
// 遍历区间主要使用 a to b 或者 a until b
// 左箭头 <- 用于为变量 a 赋值。
var x = 1;
for (x <- 1 to 10) {
println("x = " + x);
}

// for 循环集合遍历
// 通过循环可以遍历获取集合List中的值
var y = 0;
val loopList = List(0, 1, 2, 3, 4, 5);
for (y <- loopList) {
println("y = " + y);
}

// for 循环 if 过滤
// 可以在循环中加入限制条件,只遍历符合条件的语句
for (y <- loopList ; if y != 1; if y == 5) {
println("y = " + y);
}

while循环

​while​​ 循环和其他编程语言语法上是相同的:

// while 循环
var z = 0;
while (z < 5) {
println("z = " + z);
z+=1;
}

do...while循环

​do...while​​​ 循环和 ​​while​​​ 循环语句的区别,主要在于 ​​do​​ 是先处理循环逻辑,在判断条件。

// do...while 循环
var d = 0;
do {
println("d = " + d);
d+=1;
} while (d < 5)

方法与函数

方法与函数在 Scala 中的区别很小,主要是定义上的区别,通常类中定义的函数称为方法,而函数主要作用是用于给对象赋值。

而在 Scala 中使用 ​​val​​​ 语句可以定义函数,​​def​​ 语句定义方法,所以在称呼上没有明显区别。

理解并掌握以下方法的实例即可:

// addInt 为方法名
// x,y 为方法入参
// 括号后面的 Int= 表示方法返回的数据类型
def addInt( x:Int, y:Int ) : Int = {
var sum:Int = 0;
sum = x + by;
return sum;
}

def main(args : Array[String]) : Unit = {
// 将函数作为入参传入
printName(getName());
}

def getName() : String = {
return "Scala";
}

// String = "defName" 表示默认参数,如果未传参则按默认参数执行
def printName(name : String = "defName"): Unit = {
println("name is " + name);
}

// * 表示可变参数的函数,可以动态传入多个参数
def canChangVar(strs : String*) ={
var str = "";
for (str <- strs) {
println("str = " + str);
}
}

Scala 中的函数闭包可以理解为通过另外一函数访问函数局部变量。

def main(args : Array[String]) : Unit = {
println(getName("scala"));
}
// 闭包
var getName = (name : String) => "name is " + name;

Scala集合容器

Scala 提供了一套完整的集合实现,集合主要分为可变和不可变,这一点与 Java 中的集合是有所区别的。

List(列表)

List 列表是一个​不可变​的​元素可重复​的集合,属于Seq接口的子接口。

List 的值在初始化后就不能修改了,所以在使用时需要注意这个特性。

// 定义 List , 普通列表、空列表、多维列表
val strList : List[String] = List("a", "b", "c");
var nullList: List[Nothing] = List();
nullList = Nil; // Nil 表示空列表
val mulList : List[List[Int]] = List(List(1,1), List(2,2));
// head 返回列表第一个元素
println("head:"+strList.head);
// tail 返回一个列表,包含除了第一元素之外的其他元素
println("tail:" + strList.tail);
// :: 可以拼接成新的列表
println("head::tail =" + strList.head :: strList.tail);

其他详细操作,参考API文档:​ ​http://www.scala-lang.org/api/current/scala/collection/immutable/List.html​

Set(集合)

Set 是包含元素不重复的集合,根据引用的包分为可变集合和不可变集合,默认使用都是不可变集合。

Set 集合引用的可变(​​scala.collection.mutable.Set​​​ 包)和不可变(​​scala.collection.immutable.Set​​),通过引入不同包进行操作。

​scala.collection.immutable.Set​​ 集合的基本操作如下:

// 定义 set 集合,默认是 scala.collection.immutable.Set 不可变集合
var set = Set(1,2,3)
println(set.getClass.getName)
// 丢弃第一个元素并创建一个新集合返回
println(set.drop(1))

​scala.collection.mutable.Set​​ 集合的基本操作如下:

// 引入可变集合包
import scala.collection.mutable.Set

// 定义 set 集合
var set = Set(1, 2, 3)
println(set.getClass.getName) // scala.collection.mutable.HashSet
// 丢弃第一个元素并创建一个新集合返回
// println(set.drop(1))
// 可变集合基本操作
set.add(6); // 新增元素
set += 7; // 新增元素
set.remove(3); // 去除元素
set -= 1; // 去除元素
println(set) // HashSet(2, 6, 7)
// 将可变集合转换为不可变集合
val noSet = set.toSet;
println(noSet.getClass.getName) // scala.collection.immutable.Set

其他详细操作,参考API文档:​ ​http://www.scala-lang.org/api/current/scala/collection/immutable/Set.html​

Map(映射)

Map 集合和 Java 中的 Map 一样是一种 Hash 表,以键值对(​​key/value​​)结构存在。

Map 集合也包含可变(​​import scala.collection.mutable.Map​​​)和不可变 (​​scala.collection.immutable.Map​​),默认使用是不可变集合。

​scala.collection.immutable.Map​​ 集合的基本操作如下:

// Map 集合,默认使用 scala.collection.immutable.Map 不可变集合
// 通过 -> 表示键值对关系
var map: Map[String, Int] = Map("a" -> 1, "b" -> 2);
// 通过主键获取值
println(map("b")) // 2
println(map.getClass.getName) // scala.collection.immutable.Map

​scala.collection.mutable.Map​​ 集合的基本操作如下:

import scala.collection.mutable.Map

// Map 集合
// 通过 -> 表示键值对关系
var map: Map[String, Int] = Map("a" -> 1, "b" -> 2);
// 通过主键获取值
println(map("b")) // 2
println(map.getClass.getName) // scala.collection.mutable.HashMap
// 判断集合中是否存在指定值
println(map.contains("c")); // false
// 获取集合的 key 和 value
println(map.keys); // Set(a, b)
println(map.values); // Iterable(1, 2)
// 集合新增元素
map += ("c" -> 3)
println(map) // HashMap(a -> 1, b -> 2, c -> 3)

其他详细操作,参考API文档:​ ​http://www.scala-lang.org/api/current/scala/collection/immutable/Map.html​

Iterator(迭代器)

Scala 中迭代器 ​​Iterator​​​ 不是一个集合容器,而是访问集合的一个方法,如果会 Java 的化,可以知道其常用的操作有 ​​next​​​ 和 ​​hasNext​​ 。

基本使用操作:

// 定义迭代器
var iterator = Iterator(1, 2, 3, 4, 5);
// 遍历迭代器
while (iterator.hasNext) {
print(iterator.next())
}
// 获取迭代器的长度
println("长度为:" + iterator.size )

其他详细操作,参考API文档:​ ​http://www.scala-lang.org/api/current/scala/collection/Iterator.html​

通过本文总结了 Scala 的基础语法和基本操作,能够方便我们去阅读其他框架的源码,提升对于框架底层设计的思想的理解,后续将继续推出 Scala 编程的进阶速成篇,敬请期待。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK