1. intersect方法找出兩個字符串的相同字符:
scala> "Hello".intersect("World")
res3: String = lo
2. for推導式生成的集合與它的第一個生成器的類型是兼容的。
scala> for(c <- "Hello";i <- 0 to 1) yield (c + i).toChar res7: String = HIeflmlmop scala> for(i <- 0 to 1; c <- "Hello") yield (c + i).toChar res9: scala.collection.immutable.IndexedSeq[Char] = Vector(H, e, l, l, o, I, f, m, m, p)
3. 變長參數
scala> def sum(args: Int*) = { | var result = 0 | for (arg <- args) result += arg | result | } sum: (args: Int*)Int scala> val s = sum(1, 3, 4, 5, 32) s: Int = 45
scala> def recursiveSum(args: Int*): Int = { | if(args.length == 0) 0 | else args.head + recursiveSum(args.tail: _*) | } recursiveSum: (args: Int*)Int scala> recursiveSum(1 to 5: _*) res10: Int = 15
在這里,序列的head是它的首個元素,而tail是所有其他元素的序列,這又是一個Seq,我們用:_*來將它轉換成參數序列。
4. 過程
Scala對於不返回值的函數有特殊的表示法。如果函數體包含在花括號當中但沒有前面的=號,那么返回值類型就是Unit。這樣的函數被稱做過程(procedure)。過程不返回值,我們調用它僅僅是為了它的副作用。例如:
scala> def box(s: String) { | var border = "-" * s.length + "--\n" | println(border + "|" + s + "|\n" + border) | } box: (s: String)Unit scala> box("Hello") ------- |Hello| -------
5. 變長數組:數組緩沖
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 res15: b.type = ArrayBuffer(1) scala> b += (1, 2, 3, 5) res16: b.type = ArrayBuffer(1, 1, 2, 3, 5) scala> b ++= Array(8, 13, 21) res17: b.type = ArrayBuffer(1, 1, 2, 3, 5, 8, 13, 21)
scala> b.trimEnd(5) //移除最后5個元素
scala> b
res19: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 1, 2)
你也可以在任意位置插入或移除元素,但這樣的操作並不那么高效——所有在那個位置之后的元素都必須被平移。舉例如下:
scala> b.insert(2,6) //在下標2之前插入 scala> b res21: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 1, 6, 2) scala> b.insert(2,7,8,9) //可以插入任意多的元素 scala> b res23: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 1, 7, 8, 9, 6, 2) scala> b.remove(2) res24: Int = 7 scala> b res25: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 1, 8, 9, 6, 2) scala> b.remove(2,3) //第2個參數的含義是要移除多少個元素 scala> b res27: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 1, 2)
有時候你需要構建一個Array,但不知道最終需要裝多少元素。這種情況下,先構建一個數組緩沖,然后調用:
scala> b.toArray
res28: Array[Int] = Array(1, 1, 2)
反過來,調用a.toBuffer可以將一個數組a轉換成一個數組緩沖。
6. 數組轉換
從一個數組(或數組緩沖)出發,以某種方式對它進行轉換是很簡單的。這些轉換動作不會修改原始數組,而是產生一個全新的數組。
像這樣使用for推導式:
scala> val a = Array(2, 3, 5, 7, 11) a: Array[Int] = Array(2, 3, 5, 7, 11) scala> val result = for(elem <- a) yield 2*elem result: Array[Int] = Array(4, 6, 10, 14, 22)
for(...)yield循環創建了一個類型與原始集合相同的新集合。如果你從數組出發,那么你得到的是另一個數組。如果你從數組緩沖出發,那么你在for(...)yield之后得到的也是一個數組緩沖。
另一種做法是:
scala> a.filter(_ % 2 == 0).map(2 * _) res34: Array[Int] = Array(4) scala> a.filter(_ % 2 == 0) map(2 * _) res35: Array[Int] = Array(4)
7. 多維數組
和java一樣,多維數組是通過數組來實現的。舉例來說,Double的二維數組類型為Array[Array[Double]]。要構建這樣一個數組,可以用ofDim方法:
scala> val matrix = Array.ofDim[Double](3, 4) //三行,四列 matrix: Array[Array[Double]] = Array(Array(0.0, 0.0, 0.0, 0.0), Array(0.0, 0.0,0.0, 0.0), Array(0.0, 0.0, 0.0, 0.0))
要訪問其中的元素,使用兩對圓括號:
scala> matrix(0)(0) = 42 scala> matrix res2: Array[Array[Double]] = Array(Array(42.0, 0.0, 0.0, 0.0), Array(0.0, 0.0, 0.0, 0.0), Array(0.0, 0.0, 0.0, 0.0))
你可以創建不規則的數組,每一行的長度各不相同:
scala> val triangle = new Array[Array[Int]](10) triangle: Array[Array[Int]] = Array(null, null, null, null, null, null, null, null, null, null) scala> for(i <- 0 until triangle.length) | triangle(i) = new Array[Int](i + 1) scala> triangle res4: Array[Array[Int]] = Array(Array(0), Array(0, 0), Array(0, 0, 0), Array(0, 0, 0, 0), Array(0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
8. 與Java的互操作
由於Scala數組是用Java數組實現的,你可以在Java和Scala之間來回傳遞。可以引入scala.collection.JavaConversions里的隱式轉換方法。這樣你就可以在代碼中使用Scala緩沖,在調用Java方法時,這些對象會被自動包裝成Java列表。
舉例來說,java.lang.ProcessBuilder類有一個以List<Sring>為參數的構造器。以下是在scala中調用它的寫法:
scala> import scala.collection.JavaConversions.bufferAsJavaList import scala.collection.JavaConversions.bufferAsJavaList scala> import scala.collection.mutable.ArrayBuffer import scala.collection.mutable.ArrayBuffer scala> val command = ArrayBuffer("ls","-al","/home/cay") command: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer(ls, -al, /home/cay) scala> val pb = new ProcessBuilder(command) //Scala到Java的轉換 pb: ProcessBuilder = java.lang.ProcessBuilder@b37537
Scala緩沖被包裝成了一個實現了java.util.List接口的Java類的對象。
反過來講,當Java方法返回java.util.List時,我們可以讓它自動轉換成一個Buffer:
scala> import scala.collection.JavaConversions.asScalaBuffer import scala.collection.JavaConversions.asScalaBuffer scala> import scala.collection.mutable.Buffer import scala.collection.mutable.Buffer scala> val cmd: Buffer[String] = pb.command() //Java到Scala的轉換 cmd: scala.collection.mutable.Buffer[String] = ArrayBuffer(ls, -al, /home/cay) //不能使用ArrayBuffer——包裝起來的對象僅能保證是個Buffer
如果Java方法返回一個包裝過的Scala緩沖,那么隱式轉換會將原始的對象解包出來。拿本例來說,cmd == command。
9. 獲取映射中的值
scala> val scores = Map("Alice" -> 10, "Bob" -> 3, "Cindy" -> 8) scores: scala.collection.immutable.Map[String,Int] = Map(Alice -> 10, Bob -> 3, Cindy -> 8) scala> val scores = scala.collection.mutable.Map("Alice" -> 10, "Bob" -> 3, "Can dy" -> 8) scores: scala.collection.mutable.Map[String,Int] = Map(Bob -> 3, Alice -> 10, Ca ndy -> 8) scala> val scores = new scala.collection.mutable.HashMap[String,Int] scores: scala.collection.mutable.HashMap[String,Int] = Map() scala> "Alice" -> 10 res5: (String, Int) = (Alice,10) scala> scores res6: scala.collection.mutable.HashMap[String,Int] = Map() scala> val scores = Map(("Alice", 10), ("Bob", 3), ("Cindy", 8) | ) scores: scala.collection.immutable.Map[String,Int] = Map(Alice -> 10, Bob -> 3, Cindy -> 8) scala> val bobsScore = scores("Bob") bobsScore: Int = 3 scala> val bobsScore = if(scores.contains("Bob")) scores("Bob") else 0 bobsScore: Int = 3
由於這樣的組合調用十分普遍,以下是一個快捷的寫法:
scala> val bobsScore = scores.getOrElse("Bob", 0) bobsScore: Int = 3 //如果映射包含鍵“Bob”,返回對應的值;否則,返回0。