Scala進階
在后面的文章中声登,會涉及到一些Scala中我們還沒有接觸到的語法浙滤。這篇Scala進階會在Scala基礎上更進一步腾誉,完成對Scala語言特性的整體學習贵少。
1. 閉包
看下面這個例子,multiplier函數的輸出值不僅取決于輸入參數i铆惑,還與變量factor相關范嘱,而factor是聲明在函數外的。
有趣的是员魏,函數可以對這個這個factor進行修改丑蛤,仿佛factor是這個函數的一個私有變量。這就是閉包撕阎。
object Test {
def multiplier (i: Int): Int = {
factor = factor + 1
return i * factor
}
var factor: Int = 6
def main(args: Array[String]) {
println(multiplier(1))
println(multiplier(1))
}
}
輸出結果:
7
8
2. 字符串
Scala字符串使用的直接是java.lang.String受裹,因此和Java的使用方法基本一致。
用幾個例子就可以說明使用方法了闻书。
// 創(chuàng)建字符串
val greeting: String = "Hello World"
// String 對象是不可變的
// 如果你需要創(chuàng)建一個可以修改的字符串名斟,可以使用 String Builder 類
val buf = new StringBuilder;
buf += 'a'
buf ++= "bcdef"
println( "buf is : " + buf.toString );
// 字符串長度
var len = palindrome.length();
// 字符串連接
"菜鳥教程官網: ".concat("www.runoob.com");
"菜鳥教程官網: " + ("www.runoob.com");
// 格式化輸出
var fs = printf("浮點型變量為 " +
"%f, 整型變量為 %d, 字符串為 " +
" %s", floatVar, intVar, stringVar)
3. 數組Array
數組是Array脑慧,Array的特點是長度固定魄眉,元素可變,可以先定義后賦值
一維數組的創(chuàng)建方法闷袒,有三種
var z:Array[String] = new Array[String](3)
var z = new Array[String](3)
z(0) = "Runoob"; z(1) = "Baidu"; z(2) = "Google"
var z = Array("Runoob", "Baidu", "Google")
遍歷數組
for ( x <- myList ) {
println( x )
}
合并數組
var myList3 = concat( myList1, myList2)
用range來創(chuàng)建區(qū)間數組
import Array._
for (x <- range(1,10,2)) {
println(x)
}
多維數組的定義及使用
import Array._
var myMatrix = ofDim[Int](3,3)
for (i <- 0 to 2; j <- 0 to 2) {
myMatrix(i)(j) = j;
}
4. Collections
Scala的集合包括以下五種
列表List
Scala 列表類似于數組坑律,它們所有元素的類型都相同,但是它們也有所不同:列表是不可變的囊骤,值一旦被定義了就不能改變晃择。
val nums: List[Int] = List(1, 2, 3, 4)
val nums = List(1, 2, 3, 4)
// 構造列表的兩個基本單位是 Nil 和 ::
// Nil 也可以表示為一個空列表。
val nums = 1 :: (2 :: (3 :: (4 :: Nil)))
集合Set
Scala Set(集合)是沒有重復的對象集合也物,所有的元素都是唯一的宫屠。Scala 集合分為可變的和不可變的集合。默認情況下滑蚯,Scala 使用的是不可變集合浪蹂〉终唬可變需要引入包。
val set:Set[Int] = Set(1,2,3)
val set = Set(1,2,3)
哈希表Map
Map(映射)是一種可迭代的鍵值對(key/value)結構坤次。所有的值都可以通過鍵來獲取古劲。Map 中的鍵都是唯一的。默認情況下 Scala 使用不可變 Map缰猴〔可變需要引入包。
var A:Map[Char,Int] = Map()
val colors = Map("red" -> "#FF0000", "azure" -> "#F0FFFF")
// 添加元素
A += ('I' -> 1)
A += ('J' -> 5)
A += ('K' -> 10)
// 訪問元素
A('I')
元組Tuple
與列表一樣滑绒,元組也是不可變的闷堡,但與列表不同的是元組可以包含不同類型的元素。
val t = (1, 3.14, "Fred")
// 注意最多到Tuple22
val t = new Tuple3(1, 3.14, "Fred")
我們可以使用 t._1 訪問第一個元素疑故, t._2 訪問第二個元素
選項Option
Scala Option(選項)類型用來表示一個值是可選的(有值或無值)缚窿。
Option[T] 是一個類型為 T 的可選值的容器: 如果值存在, Option[T] 就是一個 Some[T] 焰扳,如果不存在倦零, Option[T] 就是對象 None
val a:Option[Int] = Some(5)
val b:Option[Int] = None
比如Map的get方法返回的就是Option對象
val myMap: Map[String, String] = Map("key1" -> "value")
val value1: Option[String] = myMap.get("key1")
val value2: Option[String] = myMap.get("key2")
println(value1) // Some("value1")
println(value2) // None
5. 迭代器Iterator
Scala Iterator(迭代器)不是一個集合,它是一種用于訪問集合的方法吨悍。
迭代器 it 的兩個基本操作是 next 和 hasNext扫茅。調用 it.next() 會返回迭代器的下一個元素,并且更新迭代器的狀態(tài)育瓜。調用 it.hasNext() 用于檢測集合中是否還有元素葫隙。
val it = Iterator("Baidu", "Google", "Runoob", "Taobao")
while (it.hasNext){
println(it.next())
}
// 獲取最值
println("最大元素是:" + ita.max )
println("最小元素是:" + itb.min )
// 獲取長度
println("ita.size 的值: " + ita.size )
println("itb.length 的值: " + itb.length )
6. 類和對象
直接用一個例子體會一下就好了,語法和Java只有微小的區(qū)別
class Point(val xc: Int, val yc: Int) {
var x: Int = xc
var y: Int = yc
def move(dx: Int, dy: Int) {
x = x + dx
y = y + dy
println ("x 的坐標點 : " + x);
println ("y 的坐標點 : " + y);
}
}
class Location(xc: Int, yc: Int,
val zc :Int) extends Point(xc, yc){
var z: Int = zc
def move(dx: Int, dy: Int, dz: Int) {
x = x + dx
y = y + dy
z = z + dz
println ("x 的坐標點 : " + x);
println ("y 的坐標點 : " + y);
println ("z 的坐標點 : " + z);
}
}
object Test {
def main(args: Array[String]) {
val loc = new Location(10, 20, 15);
// 移到一個新的位置
loc.move(10, 10, 5);
}
}
- Scala重寫一個非抽象方法躏仇,必須用override修飾符恋脚。例子里面的move方法參數不同,算是重載了焰手,所以不需要override糟描。
Scala 單例對象:Scala有個非常簡便的創(chuàng)建單例模式對象的關鍵詞object,可以實現(xiàn)類似Java下單例代碼的功能书妻,object對象不能帶有參數船响,寫法如下
object Point {
var x: Int = 1
var y: Int = 2
def move(dx: Int, dy: Int) {
x = x + dx
y = y + dy
println ("x 的坐標點 : " + x);
println ("y 的坐標點 : " + y);
}
}
object Test {
def main(args: Array[String]) {
println(Point.x)
Point.move(2,3)
}
}
Java單例模式寫法
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
伴生對象,與類共享名字躲履,可以訪問類的私有屬性和方法
7. 特征Trait
Scala Trait(特征) 相當于 Java 的接口见间,實際上它比接口還功能強大。與接口不同的是工猜,它還可以定義屬性和方法的實現(xiàn)米诉。
一般情況下Scala的類只能夠繼承單一父類,但是如果是 Trait(特征) 的話就可以繼承多個篷帅,從結果來看就是實現(xiàn)了多重繼承史侣。
trait Equal {
def isEqual(x: Any): Boolean
def isNotEqual(x: Any): Boolean = !isEqual(x)
}
當需要繼承一個類汗销,擴展多個trait時,這樣寫
class Location(xc: Int, override val yc: Int,
val zc :Int) extends Point(xc, yc) with Equal
8. 模式匹配
模式匹配和C及Java中的switch有點類似抵窒,但是Scala的模式匹配更為強大弛针,可以匹配不同數據類型。
object Test {
def main(args: Array[String]) {
println(matchTest("two"))
println(matchTest("test"))
println(matchTest(1))
println(matchTest(6))
}
def matchTest(x: Any): Any = x match {
case 1 => "one"
case "two" => 2
case y: Int => "scala.Int"
case _ => "many"
}
}
輸出結果為:
2
many
one
scala.Int
補充:使用了case關鍵字的類定義就是就是樣例類(case classes)李皇,樣例類是種特殊的類削茁,經過優(yōu)化以用于模式匹配。
9. 異常處理
拋出異常
throw new IllegalArgumentException
捕獲異常
import java.io.FileReader
import java.io.FileNotFoundException
import java.io.IOException
object Test {
def main(args: Array[String]) {
try {
val f = new FileReader("input.txt")
} catch {
case ex: FileNotFoundException => {
println("Missing file exception")
}
case ex: IOException => {
println("IO Exception")
}
} finally {
println("Exiting finally...")
}
}
}
執(zhí)行結果為
Missing file exception
Exiting finally...
10. 提取器
Scala 提取器是一個帶有unapply方法的對象掉房。unapply方法算是apply方法的反向操作:unapply接受一個對象茧跋,然后從對象中提取值,提取的值通常是用來構造該對象的值卓囚。
11. 文件I/O
寫文件
import java.io._
object Test {
def main(args: Array[String]) {
val writer = new PrintWriter(new File("test.txt" ))
writer.write("菜鳥教程")
writer.close()
}
}
讀取輸入
object Test {
def main(args: Array[String]) {
print("請輸入菜鳥教程官網 : " )
val line = Console.readLine
println("謝謝瘾杭,你輸入的是: " + line)
}
}
讀文件
import scala.io.Source
object Test {
def main(args: Array[String]) {
println("文件內容為:" )
Source.fromFile("test.txt" ).foreach{
print
}
}
}