Scala入門筆記二

標識符

可用的字符

  • 處理括號類字符,分隔符以外,其餘全部的可打印的ASCII字符,如字母,數字,下劃線和美圓符號($)都可出如今Scala標識符中
  • 插入符包括了(,) [,] {,and}
  • 分隔符包括 ` ' " . ; ,等
  • Scala還容許在標識符中使用編碼在 \u0020到\u007F之間的字符,如數學符號,想 / 和 < 這樣的操做符字符以及其餘的一些符號

不能使用保留字.數據庫

普通標識符

  • 常見的標識符每每由字母或下劃線開頭,後面跟着一些字母,數字,下劃線和$符
  • Scala容許使用Unicode格式的字符
  • $符在Scala內部會做爲特定做用,儘可能不要使用
  • Scala編譯器會將下劃線以後,空格以前的全部字符視爲標識符的一部分
  • 假如在下劃線後輸入了操做符,那麼不容許在操做符後輸入字母或數字
  • 假如某一標識符以操做符開頭,那麼後面的字符也必須是操做符字符

示例

val xyz_++= = 1

使用反引號定義標識符

能夠經過反引號定義標識符,兩個反引號內的任意長度的字符串即是定義的標識符.ide

def `test that addition work`= assert(1 + 1 = 2)

無參數方法

  • 對於不包含參數的方法,除了能夠選擇使用中綴調用或後綴調用方式以外,Scala還容許用戶靈活決定是否使用括號
  • 定義無參方法時省略了括號,那麼在調用這些方法時必須省略括號
  • 定義無參方法時添加了空括號,那麼調用該方法時能夠選擇省略或保留括號

幾個等價表達式

List(1, 2, 3, 4).filter((i: Int) => isEven(i)).foreach((i: Int) => println(i))
List(1, 2, 3, 4).filter(i => isEven(i)).foreach(i => println(i))
List(1, 2, 3, 4).filter(isEven).foreach(println)
List(1, 2, 3, 4) filter isEven foreach println

優先級規則

1. 全部字母
2. |
3. ^
4. &
5. < >
6. = !
7. :
8. + -
9. * / %
10. 其餘特殊字符
  • 全部操做符都是方法
  • 並非全部方法都是左結合
  • 任何名字以冒號(:)結尾的方法均與其右邊的對象綁定

cons操做

  • cons是constructor的縮寫
  • cons操做指經過::方法將某一元素放置到列表前面

示例

scala> val list = List('c', 'd')
list: List[Char] = List(c, d)

scala> 'a' :: list
res1: List[Char] = List(a, c, d)

scala> val list = List('c', 'd')
list: List[Char] = List(c, d)

scala> 'b' :: list
res2: List[Char] = List(b, c, d)

scala> list.::('a')
res3: List[Char] = List(a, c, d)

scala> 'a' :: list
res4: List[Char] = List(a, c, d)

scala> 'b' :: list
res5: List[Char] = List(b, c, d)

注意:this

  • 'a' :: list 等價於 list.::('a')編碼

  • 不能使用該方法重複插入多個字符es5

if語句

  • Scala的if語句能夠向Java中同樣使用scala

    if (2 + 2 = 5) {
        println("if")
    } else if (2 + 2 = 3) {
        println("else if")
    } else {
        println("else")
    }
  • Scala中的if語句是有返回值的. 能夠將if表達式的結果值賦值給其餘變量. 如下面代碼爲例.code

    val configFile = new java.io.File("someFile.txt")
    
    val configFilePath = if (configFile.exists()) {
        configFile.getAbsolutePath()
    } else {
        configFile.createNewFile()
        configFile.getAbsolutePath()
    }

    if語句返回值的類型也被稱爲全部條件分支的最小上界類型,也就是與每條each子句可能返回值類型最接近的父類型.在上面例子中,configFilePath 是if表達式的結果值,該if表達式將執行文件不存在的條件分支(假定),並返回新建立文件的絕對路徑.將if語句的返回值賦予變量configFilePath .orm

Scala不支持三元表達式對象

循環

for推導式

for循環

示例

代碼
val list = List("A", "B", "C")
  
for (item <- list)
    println(item)
輸出
A
B
C

生成器表達式

  • item <- list這樣的表達式被稱爲生成器表達式
  • 該表達式會基於集合生成單獨的數值
  • 左箭頭操做符(<-)用於對象列表這樣的集合進行遍歷

保護式: 篩選元素

  • for語句中能夠加入if表達式來篩選元素,這些表達式被稱爲保護式(guard)

示例

代碼
val list = List("ABC", "CDE", "EFG")

for (item <- list
    if item.contains("C")
    )
  println(item)
輸出
ABC
CDE

添加多個保護式

示例
val list = List("ABC", "BCD", "CDE")
  
for (item <- list
   if item.contains("B")
   if !item.startsWith("A")
    )
  println(item)
 
for (item <- list
   if item.contains("B") && !item.startsWith("A")
    )
  println(item)
輸出
BCD
BCD
  • 分別爲兩個for循環的輸出

Yielding

  • 使用yielding關鍵字能在for表達式中生成新的集合

示例

代碼
val list = List("ABC", "BCD", "CDE")
val filterItems =  for {item <- list
    if item.contains("B")
    if !item.startsWith("A")
    } yield item
filterItems
運行
scala> val list = List("ABC", "BCD", "CDE")
list: List[String] = List(ABC, BCD, CDE)

scala> val filterItems =  for {item <- list
     | if item.contains("B")
     |  if !item.startsWith("A")
     | } yield item
filterItems: List[String] = List(BCD)

擴展做用域與值定義

  • 可以在for表達式中的最初部分定義值,並可在之後的表達式中使用該值

示例

代碼
val list = List("abc", "bcd", "cde")
  
val upcaseItems = for {
    item <- list
    upcaseItem = item.toUpperCase()
} yield upcaseItem
運行
scala> val list = List("abc", "bcd", "cde")
list: List[String] = List(abc, bcd, cde)

scala>
     | val upcaseItems = for {
     | item <- list
     |     upcaseItem = item.toUpperCase()
     | } yield upcaseItem
upcaseItems: List[String] = List(ABC, BCD, CDE)

while循環

示例

while (表達式) {
    do something
}

do...while循環

示例

var count = 0
do {
    count += 1
} while(count < 10)

條件操做符

操做符 操做
&& 和操做
|| 或操做
> 大於
>= 大於或等於
< 小於
<= 小於或等於
== 等於
!= 不等於
  • &&|| 是短路操做符

  • 在Java中== 只會對對象引用進行比較, 調用equals來比較字段值; Scala使用== 符執行邏輯上的相等檢查. 即調用equals方法進行判斷.

    public class Person {
        private String name;
        private int age;
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public boolean equals(Object obj) {
            return true;
        }
    
        public static void main(String args[]) {
            Person p1 = new Person("sun", 20);
            Person p2 = new Person("li", 20);
            System.out.println(p1 == p2);
        }
    }
    // 輸出:
    false
    class Person(var name: String, var age: Int) {
        override def equals(obj: scala.Any): Boolean = true
    }
    
    val p1 = new Person("sun", 20)
    val p2 = new Person("sun", 20)
    
    println(p1 == p2)
    
    // 輸出:
    true

使用try...catch...final子句

  • Scala使用模式匹配來捕獲異常, 而Java使用單獨的catch子句來捕獲各個異常
  • 使用case NonFatal(ex) => ... 子句使用scala.util.control.NonFatal 匹配了全部的非致命性異常
  • 經過編寫throw new MyBadException(...) 拋出異常
  • 若是自定義異常是一個case類,那麼拋出異常時能夠省略new關鍵字

實例

try {
    ...
} catch {
    case NonFatal(ex) => println(s"Non fatal exception! $ex")
    case ...
} finally {
    ...
}

惰性賦值

  • 惰性賦值是與傳名參數相關的技術
  • 若是但願以延遲的方式初始化某值, 而且表達式不會被重複計算, 則須要使用惰性賦值
  • 常見應用場景
    • 因爲表達式執行代價昂貴(好比打開一個數據庫鏈接), 但願能推遲該操做, 直到確實須要表達式結果時才執行它
    • 爲了縮短模塊啓動時間, 能夠將當前不須要的某些工做推遲執行
    • 爲了確保對象中其餘字段的初始化過程能優先執行, 須要將某些字段惰性化

示例

object ExpensiveResource {
    lazy val resource: Int = init()
    def init(): Int = {
        // 某些代價昂貴的操做
        0
    }
}
  • lazy關鍵字意味着求值過程會被推遲,只有須要時纔會執行計算
  • 首次使用惰性值時, 初始化代碼纔會被執行一次, 這種只能執行一次的計算對於可變字段而言沒有任何意義.所以lazy關鍵字不能修飾var變量
  • 經過**保護式來實現惰性值

枚舉

  • Scala經過在標準庫中專門定義Enumeration類實現枚舉

示例一

代碼

// file: enum.scala
object Breed extends Enumeration {
    type Breed  = Value
    val doberman    = Value("Doberman Pinscher")
    val yorkie      = Value("Yorkshire Terrier")
    val scottie     = Value("Scottish Terrier")
    val dane        = Value("Great Dane")
    val portie      = Value("Portuguese Water Dog")
}

import Breed._

println("ID\tBreed")
for (breed <- Breed.values) println(s"${breed.id}\t$breed")

println("\nJust Terriers:")
Breed.values filter (_.toString.endsWith("Terrier")) foreach println

def isTerrier(b: Breed) = b.toString.endsWith("Terrier")

println("\nJust Terriers:")
Breed.values filter isTerrier foreach println

運行

scala enum.scala

輸出

ID      Breed
0       Doberman Pinscher
1       Yorkshire Terrier
2       Scottish Terrier
3       Great Dane
4       Portuguese Water Dog

Just Terriers:
Yorkshire Terrier
Scottish Terrier

Just Terriers:
Yorkshire Terrier
Scottish Terrier

可插入字符串

下面是一個簡單示例:

val name = "Buck Trends"
println(s"Hello, $name")

格式化

下面是幾個對可插入字符串進行格式化的示例.

scala> val gross = 100000F
gross: Float = 100000.0

scala> val net = 64000F
net: Float = 64000.0

scala> val percent = (net / gross) * 100
percent: Float = 64.0

scala> println(f"$$${gross}%.2f vs. $$${net}%.2f or ${percent}%.1f%%")
$100000.00 vs. $64000.00 or 64.0%

scala> val s = "%02d: name = %s".format(5, "Dean Wampler")
s: String = 05: name = Dean Wampler

// 原生插入器
scala> val name = "Dean Wampler"
name: String = Dean Wampler

scala> s"123\n$name\n456"
res1: String =
123
Dean Wampler
456

scala> raw"123\n$name\n456"
res2: String = 123\nDean Wampler\n456
  • 使用$$ 打印一個$
  • 使用%% 打印一個%
相關文章
相關標籤/搜索