前言
day07,我们学习了scala的函数式编程及常用高阶函数。今天学习scala的集合、模式匹配、样本类。
scala集合
在Spark中处理数据,会读到很多数据,这些数据基本都是会存储在集合中,常用的是Map和List。scala集合有Map、List、Vector和Range、Set。
Map
Map在 day04 的学习中已经介绍过,这里不单独进行介绍了,感兴趣的看下 day04-scala学习之数组、映射(Map)、元组(Tuple) 。
List
List不可变列表,LinkedList可变列表,如下是在scala命令行下进行的一些常用操作演示。
scala> val list = List(1,2,3,4,5,6)
list: List[Int] = List(1, 2, 3, 4, 5, 6)
#取值,下标从0开始
scala> list(0)
res16: Int = 1
#List元素不允许修改,强制修改会报错
scala> list(0)=10
<console>:13: error: value update is not a member of List[Int]
list(0)=10
scala>
#获取第一个元素
scala> list.head
res18: Int = 1
#获取除第一个元素以外的所有元素
scala> list.tail
res19: List[Int] = List(2, 3, 4, 5, 6)
#转换成一个String
scala> list.mkString
res20: String = 123456
#可变List,也是需要先导入包才可以。
scala> import scala.collection.mutable._
import scala.collection.mutable._
scala> val myList = LinkedList(1,2,3,4,5,6)
warning: there was one deprecation warning; re-run with -deprecation for details
myList: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3, 4, 5, 6)
#和其它集合一样,可以使用foreach等常用的函数来对LinkedList进行遍历
scala> myList.foreach(println)
1
2
3
4
5
6
#LinkedList还可以通过指针的方式来遍历,变量指向了myList,可以通过它来操纵List
scala> var cur = myList
cur: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3, 4, 5, 6)
scala>
#cur.elem 获取第一个元素
#这是对原List进行改变了,并不是返回一个新的List,从这里也可以看出LinkedList是一个可变集合
scala> while(cur != Nil){
| cur.elem = cur.elem * 2
| cur = cur.next
| }
scala> myList
res2: scala.collection.mutable.LinkedList[Int] = LinkedList(2, 4, 6, 8, 10, 12)
scala>
#也可以通过下标直接修改LinkedList中的元素值
scala> myList(1) = 5
scala> myList
res4: scala.collection.mutable.LinkedList[Int] = LinkedList(2, 5, 6, 8, 10, 12)
scala>
序列(Vector 和 Range)
Vector是一个带下标的序列,我们可以通过下标(索引号),来访问Vector中的元素,它是不可变的集合,即使你导入了scala.collection.mutable._,创建的Vector也是不可变的。
scala> var v = Vector(1,2,3,4,5,6)
v: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3, 4, 5, 6)
#Vector的下标是从0开始的,直接通过下标访问即可
scala> v(0)
res6: Int = 1
scala>
Range其实我们前面的学习中已经用过很多了,我们前面学习for循环的时候用的“1 to 5”、“1 until 5”这些其实就是Range。
scala> println(1 to 5)
Range(1, 2, 3, 4, 5)
scala> println(1 until 5)
Range(1, 2, 3, 4)
scala>
#也可以直接使用如下的方式创建Range
scala> Range(0,5)
res9: scala.collection.immutable.Range = Range(0, 1, 2, 3, 4)
scala>
#两个Range可以进行拼接,得到的是一个新的Range
scala> ('0' to '9') ++ ('A' to 'Z')
res11: scala.collection.immutable.IndexedSeq[Char] = Vector(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z)
scala>
#也可以在创建的时候直接转换成其它集合,如List、Map
scala> 1 to 5 toList
warning: there was one feature warning; re-run with -feature for details
res12: List[Int] = List(1, 2, 3, 4, 5)
scala>
Set
Set是不重复元素的集合,和列表不同,Set并不保留元素插入的顺序。
#s是不可变Set,s1是可变Set
scala> var s = Set(1,2,3)
s: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
scala> var s1 = scala.collection.mutable.Set(1,2,3)
s1: scala.collection.mutable.Set[Int] = Set(1, 2, 3)
#不管Set是否可变,都可以添加元素
scala> s1 + 10
res0: scala.collection.mutable.Set[Int] = Set(1, 2, 3, 10)
scala> s + 10
res1: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 10)
#实际上它是新生成一个Set,并不改变原有Set
scala> s
res2: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
scala> s1
res3: scala.collection.mutable.Set[Int] = Set(1, 2, 3)
scala>
#可排序的Set
scala> var s2 = scala.collection.mutable.SortedSet(1,2,3,10,8,5)
s2: scala.collection.mutable.SortedSet[Int] = TreeSet(1, 2, 3, 5, 8, 10)
模式匹配
scala的模式匹配,比java的功能更全面,应用更广泛,可以应用在很多场合,如switch语句、类型检查等。
object Demo extends App {
/**
* 模式匹配
*/
println("===========相当于switch case=============")
//定义一个变量
val ch1 = "+"
//标识符,如果ch1是+,sign=1,如果ch1=-,sign=-1,
var sign = 0
ch1 match {
case "+" => sign = 1
case "-" => sign = -1
//如果没有匹配到的,则默认就是 _
case _ => sign
}
println(sign)
println("==========匹配所有数字==============")
//2.scala的守卫,可以匹配某种类型,case _ if
var ch2 = '5'
var digit:Int = -1
ch2 match {
case '-' => println("这是一个减号")
case '+' => println("这是一个加号")
//如果ch2是数字,则转换成10进制的数字
case _ if Character.isDigit(ch2) => digit = Character.digit(ch2,10)
case _ =>println ("其它")
}
println(digit)
println("==========在模式匹配中使用变量===========")
var ch3 = "hello world"
//ch3(6)表示字符串ch3的第7个字符
ch3(6) match {
case '+' => println("+")
case '-' => println("-")
case ch123 => println(ch123)
}
println("===========匹配类型============")
//匹配类型
var ch4:Any = 1000
ch4 match {
//如果是Int类型
case x:Int => println("这是一个整数" + x)
case y:String => println("这是一个字符串" + y)
case _ => println("其它的数据类型")
}
println("=========匹配数组或者列表=============")
//匹配数组或者列表
var ch5 = Array(1,2,3,4,5 )
ch5 match {
case Array(0) => println("这是一个空数组")
case Array(x,y) => println("数组长度为2 "+ x + y )
case Array(x,y,z) => println("数组长度为3 "+ x + y + z)
case Array(x,_*) => println("数组包含多个元素,元素个数为 "+ ch5.length)
}
}
上面代码的运行结果
样本类
scala提供样本类(case class),对模式匹配进行了优化
#普通类与样本类是一样的,不同的是样本类可以放到模式匹配中
#普通类
scala> class Student(id:Int){}
defined class Student
#样本类
scala> case class Student1(id:Int){}
defined class Student1
scala>
样本类可以直接在模式匹配中使用,像如下的代码
class Vehicle {}
case class Car(name:String) extends Vehicle{}
case class Bike(name:String) extends Vehicle{}
object Demo2{
def main(args: Array[String]): Unit = {
var a : Vehicle = new Car("Car")
//判断某个对象是否属于某个类
println(a.isInstanceOf[Vehicle])
println(a.isInstanceOf[Car])
println(a.isInstanceOf[Bike])
//上面的判断也可以通过模式匹配来实现
a match {
case Car(name) => println("汽车 " + name)
case Bike(name) => println("自行车 " + name)
case _ => println("其它")
}
}
}