过程
在Scala中,定义函数时,如果函数体直接包裹在了花括号里面,而没有使用=连接,则函数的返回值类型就是Unit。这样的函数就被称之为过程。过程通常用于不需要返回值的函数。
scala> def sayHello(name:String) = "Hello," + name
sayHello: (name: String)String
scala> sayHello("ynn")
res24: String = Hello,ynn
scala> def sayHello(name:String){print("Hello,"+name);"Hello,"+name} //过程
sayHello: (name: String)Unit
scala> sayHello("ynn")
Hello,ynn
scala> def sayHello(name:String):Unit="Hello,"+name
sayHello: (name: String)Unit
scala> sayHello("ynn")
lazy值
在Scala中,提供了lazy值的特性,也就是说,如果将一个变量声明为lazy,则只有在第一次使用该变量时,变量对应的表达式才会发生计算。这种特性对于特别耗时的计算操作特别有用,比如打开文件进行IO,进行网络IO等。
scala> import scala.io.Source._
import scala.io.Source._
scala> lazy val lines = fromFile("C://Users//96467//Desktop//scala//test.txt").mkString
lines: String = <lazy>
//即使文件不存在,也不会报错,只有第一个使用变量时会报错,证明了表达式计算的lazy特性
scala> val lines = fromFile("C://Users//96467//Desktop//scala//test.txt").mkString
java.io.FileNotFoundException: C:\Users\96467\Desktop\scala\test.txt (系统找不到指定的文件。)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at scala.io.Source$.fromFile(Source.scala:91)
at scala.io.Source$.fromFile(Source.scala:76)
at scala.io.Source$.fromFile(Source.scala:54)
... 32 elided
scala> def lines = fromFile("C://Users//96467//Desktop//scala//test.txt").mkString
lines: String
异常
scala> :paste
// Entering paste mode (ctrl-D to finish)
try {
throw new IllegalArgumentException("x should not be negative")
} catch {
case _: IllegalArgumentException => println("Illegal Argument!")
} finally {
print("release resources!")
}
// Exiting paste mode, now interpreting.
Illegal Argument!
release resources!
scala> import java.io._
import java.io._
scala> :paste
// Entering paste mode (ctrl-D to finish)
try {
throw new IOException("io exception")
} catch {
case _: IllegalArgumentException => println("Illegal Argument!")
}
// Exiting paste mode, now interpreting.
java.io.IOException: io exception
at .liftedTree1$1(<console>:19)
... 37 elided
scala> :paste
// Entering paste mode (ctrl-D to finish)
try {
throw new IOException("user defined exception")
} catch {
case e1: IllegalArgumentException=> println("illegal argument")
case e2: IOException=> println("io exception")
}
// Exiting paste mode, now interpreting.
io exception
数组
- Array
在Scala中,Array代表的含义与Java中类似,也是长度不可改变的数组。此外,由于Scala与Java都是运行在JVM中,双方可以互相调用,因此Scala数组的底层实际上是Java数组。例如字符串数组在底层就是Java的String[],整数数组在底层就是Java的Int[]。
// 数组初始化后,长度就固定下来了,而且元素全部根据其类型初始化
scala> val s = new Array[Int](10)
s: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
scala> s(0)=1
scala> for (i <- 0 until s.length) println(s(i)) //遍历数组
1
0
0
0
0
0
0
0
0
0
scala> val a = new Array[String](10)
a: Array[String] = Array(null, null, null, null, null, null, null, null, null, null)
scala> a(1) = "ynn"
scala> print(a)
[Ljava.lang.String;@1c5f29c //内存地址
scala> for (i <- 0 until a.length) println(a(i))
null
ynn
null
null
null
null
null
null
null
// 可以直接使用Array()创建数组,元素类型自动推断
scala> val c = Array("hello","world")
c: Array[String] = Array(hello, world)
scala> c(0)="hi"
scala> val d = Array("leo",4)
d: Array[Any] = Array(leo, 4)
- ArrayBuffer
在Scala中,如果需要类似于Java中的ArrayList这种长度可变的集合类,则可以使用ArrayBuffer。
// 如果不想每次都使用全限定名,则可以预先导入ArrayBuffer类
scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer
// 使用ArrayBuffer()的方式可以创建一个空的ArrayBuffer
scala> val b = ArrayBuffer[Int]()
b: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()
// 使用+=操作符,可以添加一个元素,或者多个元素
scala> b += 1
res41: b.type = ArrayBuffer(1)
scala> b += (2, 3, 4, 5)
res42: b.type = ArrayBuffer(1, 2, 3, 4, 5)
// 使用++=操作符,可以添加其他集合中的所有元素
scala> b ++= Array(6, 7, 8, 9, 10)
res43: b.type = ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 使用trimEnd()函数,可以从尾部截断指定个数的元素
scala> b.trimEnd(5)
scala> for (e <- b) //增强for遍历
| println(e)
1
2
3
4
5
// 使用insert()函数可以在指定位置插入元素
// 但是这种操作效率很低,因为需要移动指定位置后的所有元素
scala> b.insert(2,9)
scala> for (e <- b) println(e)
1
2
9
3
4
5
6
scala> b.insert(3,5,6,7,8)
scala> for (e <- b) println(e)
1
2
9
5
6
7
8
3
4
5
6
// 使用remove()函数可以移除指定位置的元素
scala> b.remove(2,5) //删除索引为2的后的5个数
scala> for (e <- b) println(e)
1
2
3
4
5
6
// Array与ArrayBuffer可以互相进行转换
scala> b.toArray
res13: Array[Int] = Array(1, 2, 3, 4, 5, 6)
scala> res13.toBuffer
res14: scala.collection.mutable.Buffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6)
遍历数组
// 使用for循环和until遍历Array / ArrayBuffer
// 使until是RichInt提供的函数
scala> for (i <- 0 until b.length)
| println(b(i))
1
2
3
4
5
6
// 跳跃遍历Array / ArrayBuffer
scala> for (i <- 0 until (b.length,2))
| println(b(i))
1
3
5
// 从尾部遍历Array / ArrayBuffer
scala> for (i <- (0 until b.length).reverse)
| println(b(i))
6
5
4
3
2
1
// 使用“增强for循环”遍历Array / ArrayBuffer
scala> for (e <- b)
| println(e)
1
2
3
4
5
6
常见操作:
//创建Array数组
scala> val a = Array(1,2,34,5)
a: Array[Int] = Array(1, 2, 34, 5)
// 数组元素求和
scala> val sum = a.sum
sum: Int = 42
// 获取数组最大值
scala> val max = a.max
max: Int = 34
// 对数组进行排序
scala> scala.util.Sorting.quickSort(a)
// 获取数组中所有元素内容
scala> a.mkString
res20: String = 12534
scala> a.mkString(",")
res21: String = 1,2,5,34
scala> a.mkString("<",",",">")
res22: String = <1,2,5,34>
// toString函数
scala> a.toString //Array数组返回内存地址
res23: String = [I@1617c6c
scala> b.toString //ArrayBuffer数组返回数组内容
res24: String = ArrayBuffer(1, 2, 3, 4, 5, 6)
使用yield和函数式编程转换数组
scala> val a = Array(1,2,3,4,5)
a: Array[Int] = Array(1, 2, 3, 4, 5)
// 对Array进行转换,获取的还是Array
scala> val a2 = for (h <- a) yield h * h
a2: Array[Int] = Array(1, 4, 9, 16, 25)
scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer
scala> val b = ArrayBuffer[Int]()
b: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()
scala> b += (1,2,3,4,5)
res25: b.type = ArrayBuffer(1, 2, 3, 4, 5)
// 对ArrayBuffer进行转换,获取的还是ArrayBuffer
scala> val b2 = for (h <- b) yield h * h
b2: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 4, 9, 16, 25)
// 结合if守卫,仅转换需要的元素
scala> val a3 = for (h <- a if h % 2 == 0) yield h * h
a3: Array[Int] = Array(4, 16)
// 使用函数式编程转换数组(通常使用第一种方式)
scala> a.filter(_%2 == 0).map(2 * _)
res26: Array[Int] = Array(4, 8)
//filter 过滤数组中满足()中的条件
scala> a.filter{_%2 == 0}.map{2 * _}
res27: Array[Int] = Array(4, 8)
算法案例:移除第一个负数之后的所有负数
scala> :paste
// Entering paste mode (ctrl-D to finish)
var fnn = false
var arrayLength = a.length
var index = 0
while (index < arrayLength){
if(a(index)>=0){
index += 1
}else{
if(!fnn){fnn = true;index += 1}
else{a.remove(index);arrayLength -= 1}
}
}
// Exiting paste mode, now interpreting.
fnn: Boolean = true
arrayLength: Int = 6
index: Int = 6
scala> a.mkString(",")
res32: String = 1,2,3,4,5,-1
算法案例:移除第一个负数之后的所有负数(改良版)
// 重新构建数组
val a = ArrayBuffer[Int]()
a += (1, 2, 3, 4, 5, -1, -3, -5, -9)
keepIndexes (0,1,2,3,4,5)
a(keepIndexes(i))=Array(1,2,3,4,5,-1)
// 每记录所有不需要移除的元素的索引,稍后一次性移除所有需要移除的元素
// 性能较高,数组内的元素迁移只要执行一次即可
var foundFirstNegative = false
val keepIndexes = for (i <- 0 until a.length if !foundFirstNegative || a(i) >= 0) yield {
if (a(i) < 0) foundFirstNegative = true
i
}
//for (i <- 0 until keepIndexes.length) { a(i) = a(keepIndexes(i)) }
a.trimEnd(a.length - keepIndexes.length)
算法案例:移除第一个负数之后的所有负数(数据很多)
// 重新构建数组
val a = ArrayBuffer[Int]()
a += (1, 2, 3, 4, 5, -1, -3, -5, -9,6,7,-7,-3,10)
结果:Array(1,2,3,4,5,-1,6,7,10)
val b = ArrayBuffer[Int]()
// 每记录所有不需要移除的元素的索引,稍后一次性移除所有需要移除的元素
// 性能较高,数组内的元素迁移只要执行一次即可
var foundFirstNegative = false
val keepIndexes = for (i <- 0 until a.length if !foundFirstNegative || a(i) >= 0) yield {
if (a(i) < 0) foundFirstNegative = true
i
}
for (i <- keepIndexes) { b+=a(i) }
Map
- 创建不可变Map:
scala> val ages =Map("yangning"->20,"wurong"->19,"bailu"->18)
scala> ages("yangning") = 12
会出错:<console>:13: error: value update is not a member of scala.collection.immutable.Map[String,Int]
ages("yangning") = 12
//如此创建的Map是不可变的
- 定义可变的Map:
scala> val ages = scala.collection.mutable.Map("yangning"->20,"wurong"->14)
ages: scala.collection.mutable.Map[String,Int] = Map(wurong -> 14, yangning -> 20)
scala> ages("yangning")=12
- 另一种创建方式:
scala> val ages = Map(("yangning",12),("wurong",13))
ages: scala.collection.immutable.Map[String,Int] = Map(yangning -> 12, wurong -> 13)
- 创建一个空的HashMap:
scala> val ages = new scala.collection.mutable.HashMap[String,Int]
ages: scala.collection.mutable.HashMap[String,Int] = Map()
- 访问Map元素:
scala> val ages = new scala.collection.mutable.HashMap[String,Int] //创建一个空的HashMap
ages: scala.collection.mutable.HashMap[String,Int] = Map()
scala> ages("leo") = 23 //更新添加元素
scala> val Age = ages("leo") //获取指定key对应的value,如果key不存在,会报错
Age: Int = 23
scala> val Age = if(ages.contains("leo")) ages("leo") else 0 //使用contains函数检查key是否存在
Age: Int = 23
scala> val Age = ages.getOrElse("leo",0) //getOrElse函数
Age: Int = 23
scala> ages += ("Mike"->23,"Tom"->45) // 增加多个元素
res8: ages.type = Map(Mike -> 23, leo -> 23, Tom -> 45)
scala> ages -= "leo" //移除元素
res9: ages.type = Map(Mike -> 23, Tom -> 45)
scala> val ages2 = ages + ("Mike"->34,"Tom"->40)
ages2: scala.collection.mutable.Map[String,Int] = Map(Mike -> 34, Tom -> 40)
scala> val ages3 = ages - "Tom"
ages3: scala.collection.mutable.HashMap[String,Int] = Map(Mike -> 23)
- 遍历Map:
scala> for ((key,value) <- ages) println(key + "" + value) // 遍历map的entrySet
Mike23
Tom45
scala> for (key <- ages.keySet) println(key) // 遍历map的key
Mike
Tom
scala> for (value <- ages.values) println(value) // 遍历map的value
23
45
scala> for ((key,value) <- ages) yield (value,key) // 生成新map,反转key和value
res15: scala.collection.mutable.HashMap[Int,String] = Map(23 -> Mike, 45 -> Tom)
- 排序
scala> val ages = scala.collection.immutable.SortedMap("leo"->23,"asd"->54,"fer"->32) // SortedMap可以自动对Map的key的排序
ages: scala.collection.immutable.SortedMap[String,Int] = Map(asd -> 54, fer -> 32, leo -> 23)
scala> val ages = new scala.collection.mutable.LinkedHashMap[String,Int] // LinkedHashMap可以记住插入entry的顺序
ages: scala.collection.mutable.LinkedHashMap[String,Int] = Map()
scala> ages("leo") = 23
scala> ages("tre") = 83
scala> ages("iuih") = 93
scala> for ((key,value) <- ages) println(key + ":" + value)
leo:23
tre:83
iuih:93
Tuple
- 简单Tuple:
scala> val t = ("leo",30)
t: (String, Int) = (leo,30)
scala> t._1 // 访问Tuple
res21: String = leo
scala> t._2
res22: Int = 30
- zip操作(拉链操作)
scala> val names = Array("leo","ynn","wii")
names: Array[String] = Array(leo, ynn, wii)
scala> val age = Array(23,12,54)
age: Array[Int] = Array(23, 12, 54)
scala> val nameage = names.zip(age)
nameage: Array[(String, Int)] = Array((leo,23), (ynn,12), (wii,54))
scala> for ((name,age) <- nameage) println(name + ":" + age)
leo:23
ynn:12
wii:54