(数据科学学习手札45)Scala基础知识

一、简介

  由于Spark主要是由Scala编写的,虽然Python和R也各自有对Spark的支撑包,但支持程度远不及Scala,所以要想更好的学习Spark,就必须熟练掌握Scala编程语言,Scala与Java较为相似,且在Scala中可以调用很多Java中的包,本文就将针对Scala中的基础数据结构、循环体以及错误处理机制进行基础的介绍;

 

二、基础数据类型与数据结构

2.1基础数据类型

  Scala包括了8种基础数据类型,基本信息如下表:

基本类型 取值范围或示例
Byte -128~127
Char U+0000~U+FFFF
Short -32768~32767
Int -2147483648~2147483647
Long -9223372036854775808~9223372036854775807
Float 单精度浮点数,如0.1f
Double 双精度浮点数,如0.11
Boolean true或false


  String也属于Scala基本数据类型,归属于java.lang包,其余的数据类型都是Scala自带基础类型包的成员,且在Scala中基本类型包与java.lang包是默认导入的。

2.2 Scala变量声明

  和java类似,Scala中的变量需要在创建时进行声明,有var和val两种声明方式,其中val类型变量定义后不可以重新赋值,而var类型变量声明之后可以自由赋新值,下面在Scala控制台中演示:

//利用val进行变量的声明
scala> val x = 0
x: Int = 0

scala> x = 5
:11: error: reassignment to val
       x = 5
         ^
//利用var进行变量的声明
scala> var x = 0
x: Int = 0

scala> x = 8
x: Int = 8

可以看到,val声明后的变量不可重新赋值,而var则可以。

  Scala中的变量声明有两种形式,一种是在声明变量时指出变量的具体类型:

scala> val x:Int=10
x: Int = 10

scala> val y:Double=1.00
y: Double = 1.0

scala> val z:String="scala"
z: String = scala

  而事实上,即使你在Scala中声明变量时不进行类型的指定,Scala内部也会根据你输入数据的具体类型进行判断,来自动分配数据类型,这是第二种变量声明的方式:

scala> val x=10
x: Int = 10

scala> val y=1.0f
y: Float = 1.0

scala> val z="spark"
z: String = spark

 

2.3 算数操作符、关系运算符与逻辑运算符

  Scala像很多其他成熟的编程语言一样,具有丰富的内置运算符,且在Scala中操作符也被视为函数,即可以通过对象.操作符()的方式使用,Scala中的常用运算符如下:

运算符 描述
+ 加运算
- 减运算
* 乘运算
/ 除运算
% 求模运算,返回余数

  而Scala中的关系运算符如下:

运算符 描述
== 判断两个对象是否相等
!= 判断两个对象是否不等
> 判断是否左大于右
< 判断是否左小于右
>= 判断是否左大于等于右
<= 判断是否左小于等于右

  Scala中的逻辑运算符如下:

运算符 描述
&& 逻辑与
|| 逻辑或
! 逻辑非

  Scala中的赋值运算符如下:

运算符 描述
= 将右侧的值赋给左对象
+= 先做加法再赋值
-= 先做减法再赋值
*= 先做乘法再赋值
/= 先做除法再赋值
%= 先做求模取余再赋值

2.4基础数据结构

2.4.1定长数组与可变数组

基本概念:

  在Scala中,数组分为可变(mutable)和不可变(immutable)数组,默认情况下定义的数组为不可变数组,若要定义可变数组,需要导入包scala.collection.mutable.ArrayBuffer,下面是一个示例:

//定义不可变长数组
scala> var array = Array(1,2,3,4)
array: Array[Int] = Array(1, 2, 3, 4)

//导入可变长数组所在包
scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer

//创建可变长数组
scala> var arrayBuffer = ArrayBuffer(1,2,3,4)
arrayBuffer: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4)

数组相关方法:

  1.索引

  对于数组,我们使用 数组名(n) 的方式来索引其从第0位开始第n+1个元素:

 

scala> var array=Array("I","You","He","Her","It")
array: Array[String] = Array(I, You, He, Her, It)

scala> array(1)
res0: String = You

 

  2.将不可变数组转换为可变数组

  我们使用.toBuffer来完成Array到ArrayBuffer的转变:

scala> var array = Array(1,2,3)
array: Array[Int] = Array(1, 2, 3)

scala> array.toBuffer
res1: scala.collection.mutable.Buffer[Int] = ArrayBuffer(1, 2, 3)

  3.获取数组长度

  我们使用.length方法来获取数组的长度:

scala> var array10 = new Array[Int](10)
array10: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)

scala> array10.length
res2: Int = 10

  4.在可变数组末尾添加元素

  我们用 += 的方式为可变长数组在其末尾添加单个或多个元素:

//创建可变长数组
scala> var arrayBuffer = ArrayBuffer(1,2,3)
arrayBuffer: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)

//在创建好的可变长数组的末尾添加单个元素4
scala> arrayBuffer += 4
res3: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4)

//在创建好的可变长数组的末尾添加多个元素
scala> arrayBuffer += (5,6,7)
res4: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6, 7)

  5.在可变长数组末尾追加任何数组

scala> var buff1 = ArrayBuffer(1,2,3)
buff1: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)

scala> var buff2 = ArrayBuffer(4,5)
buff2: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(4, 5)

scala> buff1 ++= buff2
res1: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5)

  6.移除最末端n个元素

  我们使用.trimEnd(n)来移除数组末端的n个元素:

scala> var arrayBuffer = ArrayBuffer(1,2,3,4,5,6)
arrayBuffer: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6)

scala> arrayBuffer.trimEnd(3)

scala> arrayBuffer
res1: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)

  7.移除最前端n个元素

  我们使用.trimStart(n)来移除数组前端的n个元素:

scala> var arrayBuffer = ArrayBuffer(1,2,3,4,5,6)
arrayBuffer: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6)

scala> arrayBuffer.trimStart(3)

scala> arrayBuffer
res1: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(4, 5, 6)

  8.移除数组中指定位置的元素

  我们使用.remove(n)来移除数组中下标为n的元素:

scala> var arrayBuffer = ArrayBuffer(0,1,2,3,4,5)
arrayBuffer: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(0, 1, 2, 3, 4, 5)

scala> arrayBuffer.remove(3)
res2: Int = 3

scala> arrayBuffer
res3: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(0, 1, 2, 4, 5)

  9.从数组中指定位置开始移除若干个元素

  我们依旧使用.remove(n,m)来移除数组中下标为n的元素开始往后的m个元素:

scala> var arrayBuffer = ArrayBuffer(0,1,2,3,4,5)
arrayBuffer: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(0, 1, 2, 3, 4, 5)

scala> arrayBuffer.remove(3)
res2: Int = 3

scala> arrayBuffer
res3: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(0, 1, 2, 4, 5)

scala> var arrayBuffer = ArrayBuffer(0,1,2,3,4,5)
arrayBuffer: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(0, 1, 2, 3, 4, 5)

scala> arrayBuffer.remove(2,2)

scala> arrayBuffer
res5: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(0, 1, 4, 5)

 

2.4.2 Map映射

  与Python中的字典相似,Scala中的映射就是键值对的集合Map,默认情况下Scala中同样是使用不可变的映射,想要使用可变的映射就必须导入scala.collection.mutable.Map类。

  1.定义映射

  我们用->连接键值,左边为键,右边为值,键唯一:

 

scala> var DemoMap = Map("Scala"->1,"Python"->2,"R"->3)
DemoMap: scala.collection.immutable.Map[String,Int] = Map(Scala -> 1, Python -> 2, R -> 3)

 

  2.Map映射的索引

  直接通过调用键来获取对应的值:

scala> DemoMap("Python")
res1: Int = 2

  3.判断映射中是否包含某个键的键值对

  我们使用.contains(键名)来判断某个映射中是否包含指定键名的键值对:

scala> DemoMap.contains("SQL")
res2: Boolean = false

  4.按下标获取键值对

  我们使用.drop(n)来获取指定映射中下标为2及其之后下标的键值对:

scala> DemoMap.drop(1)
res7: scala.collection.immutable.Map[String,Int] = Map(Python -> 2, R -> 3)

  5.构造可变映射

  为了构造可变的映射,我们需要导入相关包或在Map定义时输入完整路径,这里建议后者:

scala> var DemoMap = scala.collection.mutable.Map("Python"->1,"Java"->2,"R"->3)
DemoMap: scala.collection.mutable.Map[String,Int] = Map(R -> 3, Java -> 2, Python -> 1)

  6.为可变映射更新或新增键值对

//更新已有的可变Map映射中指定键的值,若不存在此键则创造新键值对
scala> DemoMap("Julia") = 100

scala> DemoMap
res1: scala.collection.mutable.Map[String,Int] = Map(R -> 3, Julia -> 100, Java -> 2, Python -> 1)

  7.提取Map映射中的键集合

  我们使用.keySet来提取Map映射中的键名集合:

scala> DemoMap.keySet
res3: scala.collection.Set[String] = Set(R, Julia, Java, Python)

  8.提取Map映射中的值集合

scala> DemoMap.values
res4: Iterable[Int] = HashMap(3, 100, 2, 1)

  9.逐个的获取Map映射中的键值对信息

scala> for((k,v) <- DemoMap)println(k,"->",v)
(R,->,3)
(Julia,->,100)
(Java,->,2)
(Python,->,1)

 2.4.3 Tuple元组

  与Python中的元组类似,Scala中的tuple元组也是圆括号包住的,可以存放不同类型的若干元素,且无论是用var还是val方式声明,元组中的元素都不可改变,且元组对内部元素的索引比较特别,是通过._n来索引其内部第n个元素(这里不从0开始):

//声明一个元组
scala> var tuple1 = (1,2,"3",4.0f,5.0)
tuple1: (Int, Int, String, Float, Double) = (1,2,3,4.0,5.0)

//对元组中的第一个元素进行索引
scala> tuple1._1
res0: Int = 1

//尝试修改元组中的固有元素
scala> tuple1._1 = 3
:11: error: reassignment to val
       tuple1._1 = 3

 

2.4.4 List列表

  也是和Python中的List类似,Scala中的列表被设计来存放各种类型的元素,且Scala中的列表类型有三种模式,一种是当列表内部元素类型统一时,如List[Int],一种是当列表中同时包含几种不同类型元素时,为List[Any],最后一种是当列表中不存放任何元素时,为List[Nothing]:

  1.定义不同的列表

scala> var list1 = List(1,2,3)
list1: List[Int] = List(1, 2, 3)

scala> var list1 = List("1","2")
list1: List[String] = List(1, 2)

scala> var list1 = List("1",2)
list1: List[Any] = List(1, 2)

scala> var list1 = List()
list1: List[Nothing] = List()

  2.构建多维列表

  在Scala中,和Python类似,也可以通过多层列表的嵌套来制造多维列表:

 

//声明一个二维列表
scala> var list1 = List(List(1,1),List(2,3))
list1: List[List[Int]] = List(List(1, 1), List(2, 3))

scala> list1(0)(1)
res0: Int = 1

 

  3.列表的拼接方式

  在Scala中,我们可以通过:::运算符或List.concat()来为已有的列表串联上新的列表:

scala> var list1 = List(1,2,3)
list1: List[Int] = List(1, 2, 3)

scala> var list2 = List(4,5)
list2: List[Int] = List(4, 5)

scala> list1:::list2
res0: List[Int] = List(1, 2, 3, 4, 5)

scala> List.concat(list1,list2)
res1: List[Int] = List(1, 2, 3, 4, 5)

scala> List.concat(list2,list1)
res2: List[Int] = List(4, 5, 1, 2, 3)

  4.列表的一些特殊索引方法

  和数组类似,列表中也有一些针对头尾若干元素的特殊的索引方式和特殊的判断列表属性的方法:

scala> var list1 = List(1,2,3,4)
list1: List[Int] = List(1, 2, 3, 4)
//使用.head方法获取第一个元素
scala> list1.head
res0: Int = 1
//使用.tail方法获取除第一个元素之外的全部元素
scala> list1.tail
res1: List[Int] = List(2, 3, 4)

 

2.4.5 Set集合

  和Python中的集合类似,Scala中的集合只允许不重复的若干元素存放在其中,因此可以用来去重,且Set集合分为不可改变的和可变的,即其本身能否被重新赋值或更改,默认情况下Scala中使用不可变的集合,若想使用可变集合就需要使用scala.collection.mutable.Set

//声明不可变长集合
scala> var set1 = Set(1,2,3,3,4)
set1: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 4)

//声明可变长集合
scala> var set2 = scala.collection.mutable.Set(1,2,2,3)
set2: scala.collection.mutable.Set[Int] = Set(1, 2, 3)

 

可以看到,无论是不可变长还是可变长集合,都完成了对输入元素的去重操作,且Set集合的head、tail、isEmpty操作与List基本一致,这里不再赘述。

  1.向集合中增减新元素

  我们使用.+()和.-()方法完成对集合中元素的添加或删减:

scala> set2.+(4)
res0: scala.collection.mutable.Set[Int] = Set(1, 2, 3, 4)

scala> set2.-(2)
res1: scala.collection.mutable.Set[Int] = Set(1, 3)

  2.判断集合中是否包含指定的元素

  我们使用.contains()方法来判断集合中是否包含指定的元素:

scala> set2.contains(1)
res3: Boolean = true

  3.返回两个集合的交集、差

   我们使用.&()方法和.&~()方法来得到两个集合的交集和差集

scala> var set1 = Set(1,2,3,4)
set1: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 4)

scala> var set2 = Set(3,4,5,6)
set2: scala.collection.immutable.Set[Int] = Set(3, 4, 5, 6)

scala> set1.&(set2)
res0: scala.collection.immutable.Set[Int] = Set(3, 4)

scala> set1.&~(set2)
res1: scala.collection.immutable.Set[Int] = Set(1, 2)

  4.计算集合中满足指定条件的元素的个数

  我们使用.count()来实现此功能:

 

scala> var set1 = Set(1,2,2,3,4,5,5,5,6)
set1: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 3, 4)

scala> set1.count(_ > 2)
res0: Int = 4

 

  5.集合转换为不可变长数组和可变长数组

scala> var set1 = Set("1","2","3")
set1: scala.collection.immutable.Set[String] = Set(1, 2, 3)

scala> set1.toArray
res0: Array[String] = Array(1, 2, 3)

scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer

scala> set1.toBuffer
res1: scala.collection.mutable.Buffer[String] = ArrayBuffer(1, 2, 3)

  6.快速判断集合中是否存在满足指定条件的元素

scala> var set1 = Set(1,2,3,4,5)
set1: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)

scala> set1.exists(_ > 4)
res0: Boolean = true

  7.得到集合中所有元素的乘积

scala> var set1 = Set(1,2,3,4,5,6,7)
set1: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 7, 3, 4)

scala> set1.product
res0: Int = 5040

  8.得到集合中所有元素的个数

scala> set1.product
res0: Int = 5040

scala> set1.size
res1: Int = 7

  9.得到一个集合中的最大值、最小值和所有元素之和

scala> var set1 = Set(1,2,3,4,5,6)
set1: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 3, 4)

scala> set1.max
res0: Int = 6

scala> set1.min
res1: Int = 1

scala> set1.sum
res2: Int = 21

 

三、条件语句和循环语句

3.1条件语句

  Scala中的if条件语句与R中的相似,主要有两种形式:

  1、if(布尔表达式)  x else y

object Main {
//创建一个main方法
  def main(args: Array[String]): Unit = {
    var x = 1
    if(x >= 0) println("Yes") else println("Nope")
  }
}

  2、if(布尔表达式){

      ......

      } else {

      ......

      }

 

object Main {
  def main(args: Array[String]): Unit = {
    var x = 1
    if(x >= 0){
      println("Yse")
    } else {
      println("Nope")
    }
  }
}

 

  3、利用类似三目运算符的形式为变量赋值

scala> var x = 10
var y = if(x > 0)x else 100
x: Int = 10

scala> y: Int = 10

 

3.2循环语句

  Scala中的循环语句主要有三种:

  1、for循环

  Scala中for循环的语法格式为:

  for(变量<-集合){

    循环体

    }

  可以用m to n或m until n来定义循环遍历的集合,to表示左右都包括,until不包含右边:

scala> for(i <- 1 to 10){
  println(i)
}
     |      | 1
2
3
4
5
6
7
8
9
10
scala> for(i <- 1 until 10){
  println(i)
}
     |      | 1
2
3
4
5
6
7
8
9

  还可以在循环中添加条件语句:

scala> for(i <- 1 until 10 if i % 2 == 0){
  println(i)
}
     |      | 2
4
6
8

  多个for循环结构体嵌套枚举:

scala> for(i <- 1 to 3;j <- 2 to 4)print(i*j+" ")
2 3 4 4 6 8 6 9 12 

  利用for循环和关键词yield来返回新的序列:

scala> var seq1 = for(i <- 1 to 10 if i%3 == 0) yield i
seq1: scala.collection.immutable.IndexedSeq[Int] = Vector(3, 6, 9)

  2、while循环

  和R中的while语法相似,在Scala中while循环的格式同样为:

  while(条件表达式){

    循环体

 }

scala> var i = 1
while(i <= 10){
  print(i+" ")
  i += 1
}
i: Int = 1

scala>      |      |      | 1 2 3 4 5 6 7 8 9 10 

  由于在Scala中没有自带break、continue两个关键字,所以要实现continue的功能可以使用if语句来控制,而要实现break功能,则需要调取相关包scala.util.control.Breaks._:

import scala.util.control.Breaks._

object Main {
  def main(args: Array[String]): Unit = {
    var i = 1
    while(true){
      if(i >= 10){
        println("stop")
        break
      }else{
        i += 1
        println(i)
      }
    }
  }
}

  3.do-while

  do-while循环和while循环相似,区别在于do-while循环至少都会运行一次循环体内的代码,其使用格式如下:

  do{

  循环体内容

  }while(条件表达式)

import scala.util.control.Breaks._

object Main {
  def main(args: Array[String]): Unit = {
    var i = 1
    do{
      println(i)
      i += 1
    }while(i<=0)
  }
}

 

3.3异常控制

  Scala中的异常控制与Java非常相似,处理抛出异常之外,还有捕获异常,这里我们只介绍捕获异常:

  Scala中捕获异常的格式如下:

  try{

           ... ...

  }catch{

      case ex:错误类型 => 捕获指定错误后的执行内容

}

在catch中捕获异常或错误,可以像上面一样指定错误类型与对应的处理方法,也可以用case ex:Exception => 的方式来更加泛型的捕获任何错误:

import scala.io.Source

object Main {
  def main(args: Array[String]): Unit = {
    try{
      val file = Source.fromFile("F://test.txt")
      val lines = file.getLines()
      for(content <- lines){
        println(content)
      }
    }catch{
      case ex:Exception => println(ex)
    }finally {
      println("结束")
    }
  }
}

运行结果:

 

 

  以上就是本文的全部内容,如有笔误,望指出。

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:((数据科学学习手札45)Scala基础知识)