上一篇中我们介绍了scala中的变量,常量的定义,然后各种分支循环语句的介绍以及函数的介绍。这篇中我们接着上面来介绍scala的基础语法。
lazy特性
在scala中有一种特殊的性质:懒加载 。这种性质也是scala中非常重要的一种性质,在spark中,就利用这种 特性是实现了transformation操作以及action操作。在scala中,懒加载就是说将一个变量使用lazy关键字声明之后,该变量就具有懒加载的性质,即只有变量 第一次被使用的时候才会计算表达式的结果。这种性质对于非常耗时的操作很有用,比如打开文件的IO,进行网络IO等。
可以看下面这个简单的案例,我们来读取一个文件,但是该文件不存在,由于我们将变量声明为了lazy,因此读取文件时不会报错(在Java中读取不存在文件时抛出异常),只有在使用这个变量时才会抛出异常。
scala> lazy val lines=fromFile("C://Users//Administor//Desktop//test.txt").mkString
lines: String = <lazy>
scala> lines.toString
java.io.FileNotFoundException: C:\Users\Administor\Desktop\test.txt (系统找不到指定的路径。)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(Unknown Source)
at java.io.FileInputStream.<init>(Unknown Source)
异常
在scala中的异常处理与Java中的异常处理机制相似,不过个人感觉要比Java中的处理更加灵活。先看一个 Demo:
try{
throw new FileNotFoundException("file not found")
}catch{
case ex:FileNotFoundException=>println("IIIegal path!")
}finally{
println("release resources")
}
Array
scala中的Array与Java中的类似,都是长度不可变的数,scala是基于JVM运行,所以scala的数组的底层就是Java数组。
数组初始化时,数组中基本元素都会固定下来,并且初始化为0。
scala> val a=new Array[Int](10)
a: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
scala> a(0)=1
scala> a
res5: Array[Int] = Array(1, 0, 0, 0, 0, 0, 0, 0, 0, 0)
也可以使用Array直接创建数组,这样scala会自动类型推断。
scala> val b=Array("hello","world")
b: Array[String] = Array(hello, world)
scala> b(0)
res6: String = hello
所以在创建的数组中的元素不一定是同一中类型的元素,可以是多种类型的元素,比如Array数组中的第一个 元素是Int,第二个元素是String,那么Array数组的元素是Int和String的公共父类Any。
scala> val arr=Array(12,"shinelon")
arr: Array[Any] = Array(12, shinelon)
ArrayBuffer
scala中也有类似于Java ArrayList中的变长数组,在使用ArrayBuffer时需要导入包scala.collection.mutable.ArrayBuffer,下面创建一个变长数组,使用+=符号向一个数组中添加元素,使用++=符号向一个数组中添加另一个数组中的元素:
scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer
scala> var buf=new ArrayBuffer[Int]()
buf: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()
scala> buf+=1
res7: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1)
scala> buf+=2
res8: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2)
scala> buf++=Array(3,4,5,6)
res10: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6)
使用trimEnd函数可以从数组尾部截断指定元素:
scala> buf++=Array(3,4,5,6)
res10: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6)
scala> buf
res11: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6)
scala> buf.trimEnd(2)
scala> buf
res13: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4)
使用insert函数在指定位置插入一个或者多个元素,不过这种方式效率很低,因为数组插入元素需要移动其他元素:
scala> buf.insert(4,5,6) //在第四个位置插入元素5,6
scala> buf
res16: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6)
使用remove函数可以删除指定位置的元素,也可以指定范围来删除元素:
scala> buf
res16: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6)
scala> buf.remove(1)
res17: Int = 2
scala> buf
res18: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 3, 4, 5, 6)
scala> buf.remove(1,3)
scala> buf
res20: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 6)
ArrayBuffer与Array也可以相互转换。使用toArray将ArrayBuffer转换为Array,使用toBuffer将Array转换为ArrayBuffer。
还可以使用for循环和until来遍历ArrayBuffer和Array。
scala> for(i <- 0 until b.length)
| println(b(i))
hello
world
也可以跳跃式遍历ArrayBuffer和Array:
scala> buf
res25: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 6, 4, 5, 7, 8)
scala> for(i <- 0 until (buf.length,2))
| println(buf(i))
1
4
7
从尾部遍历数组:
scala> for(i <- (0 until buf.length).reverse)
| println(buf(i))
8
7
5
4
6
1
使用for循环增强语句遍历:
scala> for(i <- buf)
| println(i)
1
6
4
5
7
8
数组的常见操作:
使用 sum函数求和:
scala> val a=Array(1,2,3,4,5)
a: Array[Int] = Array(1, 2, 3, 4, 5)
scala> a.sum
res29: Int = 15
max函数求最大值:
scala> println(a.max)
5
数组元素快速排序:
scala> scala.util.Sorting.quickSort(a)
使用mkString函数操作数组:
scala> a.mkString
res33: String = 12345
scala> a.mkString(",")
res34: String = 1,2,3,4,5
scala> a.mkString("<",",",">")
res35: String = <1,2,3,4,5>
也可以使用yield来进行数组之间的转换操作:
scala> val a2=for(i <- a) yield i*i
a2: Array[Int] = Array(1, 4, 9, 16, 25)
我们也可以使用函数式编程(后面会详细讲解)来操作数组:
scala> a.filter(_%2==0).map(2*_)
res37: Array[Int] = Array(4, 8)
Map、SortedMap、LinkedHashMap
Map的创建方式很简单,我们可以创建可变的Map和不可变的Map,在scala.collection包下有两个子包,scala.collection.mutable和scala.collection.immutable包,下面我们来创建一个Map:
//创建不可变Map
scala> val map=Map(("shinelon"->19),("tom"->20),("huahua"->25))
map: scala.collection.immutable.Map[String,Int] = Map(shinelon -> 19, tom -> 20, huahua -> 25)
使用同样的方式,我们可以创建一个可变的Map:
//创建可变 map
scala> val mutableMap=scala.collection.mutable.Map(("shinelon"->"good"),("tom"->"ordinary"))
mutableMap: scala.collection.mutable.Map[String,String] = Map(tom -> ordinary, shinelon -> good)
也可以如下面的方式来创建Map:
scala> val map2=Map(("hello","world"),("very","good"))
map2: scala.collection.immutable.Map[String,String] = Map(hello -> world, very -> good)
创建一个空的Map:
scala> val ages=new scala.collection.mutable.HashMap[String,Int]
ages: scala.collection.mutable.HashMap[String,Int] = Map()
访问Map中的元素,如果访问的元素不存在就会报错:
scala> println(map("shinelon"))
19
也可以使用contains函数检查key是否存在:
scala> val age=if(map.contains("shinelon")) map("shinelon") else 0
age: Int = 19
我们也有更加简便的方式来获取Map元素,如果不存在可以返回指定值,使用getOrElse函数:
scala> val age=map.getOrElse("shinelon",0)
age: Int = 19
scala> val age=map.getOrElse("shine",0)
age: Int = 0
修改可变Map的值:
修改可变Map的值,直接将新值赋值给变量覆盖旧值即可:
scala> mutableMap("shinelon")="20"
scala> mutableMap("shinelon")
res5: String = 20
向Map中 添加元素:
scala> mutableMap+=("Mike"->"best","hailun"->"better")
res7: mutableMap.type = Map(hailun -> better, Mike -> best, tom -> ordinary, shinelon -> 20)
删除Map中的元素:
scala> mutableMap-="hailun"
res8: mutableMap.type = Map(Mike -> best, tom -> ordinary, shinelon -> 20)
修改不可变Map:
修改不可变Map和上面的方式一样,唯一的区别就是将上面进行的操作赋值给另外一个变量即可,比如添加元素:
scala> val maps=map+("mike"->25)
maps: scala.collection.immutable.Map[String,Int] = Map(shinelon -> 19, tom -> 20, huahua -> 25, mike -> 25)
遍历Map:
scala> for((key,value)<-map) println(key+" "+value)
shinelon 19
tom 20
huahua 25
scala> for(key<-map.keySet) println(key)
shinelon
tom
huahua
scala> for(value<-map.values) println(value)
19
20
25
生成新Map,反转key和value:
res14: scala.collection.immutable.Map[Int,String] = Map(19 -> shinelon, 20 -> tom, 25 -> huahua)
在上面创建Map的时候我们也可以观察到,我们添加的元素是无序的,并且Map内元素的顺序并不是像我们添加时的顺序一样排列,因此我们可以使用SortedMap对元素进行排序,不过它是immutable包下的类:
scala> val ages=scala.collection.immutable.SortedMap("leo"->30,"alice"->15,"jen"->25)
ages: scala.collection.immutable.SortedMap[String,Int] = Map(alice -> 15, jen -> 25, leo -> 30)
如果我们想要map中的元素像我们插入元素的顺序一样的话,可以使用LinkedHashMap:
scala> val ages=new scala.collection.mutable.LinkedHashMap[String,Int]
ages: scala.collection.mutable.LinkedHashMap[String,Int] = Map()
scala> ages("leo")=25
scala> ages("alice")=15
scala> ages("jen")=20
scala> ages
res18: scala.collection.mutable.LinkedHashMap[String,Int] = Map(leo -> 25, alice -> 15, jen -> 20)
Map的每一个元素实际上是一个Tuple类型,下面是创建一个Tuple类型,并且访问它的元素
scala> val t=("hello","world")
t: (String, String) = (hello,world)
scala> t._1
res19: String = hello
scala> t._2
res20: String = world