程式扎記: [Scala 小學堂] Scala Gossic : 起步走 - 常用物件 (String)

標籤

2016年4月20日 星期三

[Scala 小學堂] Scala Gossic : 起步走 - 常用物件 (String)

轉載自 這裡 
前言 :
Scala 是一個可直譯、編譯、靜態、運行於 JVM 之上、可與 Java 互操作、融合物件導向編程特性與函式編程風格的程式語言. 從一些簡單的語法開始,了解 Scala 的許多特性,所以就算是起步走,東西也夠多了. 簡單的小程式可以使用 scala 指令,編譯的事就交給 scalac,編譯想快點就用 fsc. (Scala 官網), 在變與不變之間,先體會 Scala 更多特性.

String :
在 Scala 中,重用了 Java 的字串類別 java.lang.String,所以基本上,Scala 中字串與 Java 中的字串有著相同的特性(可以參考 那些字串二三事)。你可以在Scala 中直接用雙引號宣告字串,或者是使用字元陣列來建構字串,例如 :
- String1.scala 代碼 :
  1. val str1 = "Scala"  
  2. val str2 = new String(Array('S','c','a','l','a'))  
  3. println(str1)  
  4. println(str2)  

字串是不可變動的(Immutable),在建立之後就不能改變它的值,在內部字串是使用陣列儲存字元資料,你可以根據索引取得字串中的字元值,基本上你可以使用 charAt 方法,索引由 0 開始,例如 str1.charAt(0) 傳回'S'字元,str1.charAt(1) 傳回 'c' 字元,',以下是幾個與索引相關的方法(直接引自 java.lang.String 的方法宣告方式):


要取得字串長度資訊,也是透過 String 類別的 length 方法來取得,簡單來說,只要查詢 java.lang.String 的API,就可以知道在Scala中,字串有哪些方法可以操作. 除了使用 Java 的方式來操作字串之外,在 Scala 中,你還可以對字串作更多的操作,例如,有剖析字串,可以使用 toInttoLong、 toDouble 等方法(在 Java 中則是使用對應 Wrapper 類別的 parseXXX() 方法),也可以將某個字串「乘以」某數,表示重複字串幾次 :
  1. println("123".toInt + "456".toInt)  
  2. println("Scala" * 3)  
若要循序取出字串中每個字元,可以使用 for 運算式 :
  1. for(c <- nbsp="" span="">"Scala") {  
  2.     println(c) // 每行顯示一個字元  
  3. }  
簡單的函式 曾介紹過的 foreach 方法,在字串上也可以使用 :
"Scala".foreach((c: Char) => println(c)) // 每行顯示一個字元

事實上,如果你要指定索引,取得字串中的字元,除了 charAt 方法之外,使用以下的方式會更為直覺 :
val str = "Scala"
println(str(0)) // 顯示 'S' 
println(str(1)) // 顯示 'c' 
println(str(4)) // 顯示 'a'

這並不是什麼神奇的功能,事實上當你操作字串時,呼叫了某個 java.lang.String 上所沒有提供的方法時,Scala 會使用隱式轉換(Implicit conversion)將字串使用 scala.collection.immutable.StringOps (RichString 自 2.7x 之後已經被改為了 StringOps) 包裹起來,上面幾個例子,實際上都是操作 StringOps 上的某些方法才得以完成(其中一些關於產生器、foreach、apply方法等,之後還會詳述). 在字串中若要表示特定字元,例如"號,則要使用 \ 來跳脫(Escape),例如 :
val str = "This is \"Scala\"!"
println(str) // 顯示 This is "Scala" !

以下是跳脫字元的指定方式 :

在Scala中,可以使用 """ 來括住字串,稱之為 原始字串Raw string),上面的例子可以寫為以下形式
val str = """This is "Scala"!"""
println(str) // 顯示 This is "Scala" !

在原始字串中,你不用跳脫字元,所以可以直接在原始字串中寫下"、\符號,不用特別跳脫"、\符號,對於撰寫正則表示式(Regular expression)時的簡潔很有幫助,例如原先撰寫以下的正則表示式 :
val re = "\\d\\d\\d"
println("123-134".replaceAll(re, "###"))

因為正則表示式\d要寫在字串中,必須跳脫\符號,所以必須寫成\\d。如果使用Scala的原始字串,則只要寫成 :
val re = """\d\d\d"""
println("123-134".replaceAll(re, "###")) // 顯示 ###-###

原始字串也可以跨越多行 :
  1. val text = """在原始字串中,你不用跳脫字元,  
  2.               所以可以直接在原始字串中寫下"  
  3.               、\符號,不用特別跳脫"、\符號..."""  
  4. println(text)  
上面的程式看似只是縮排,不過要注意,在跨越多行時,空白也會被列為字串的一部份,所以程式執行後會顯示 :

如果不想連同空白也被列入,則可以使用 | 符號加上 stripMargin 方法,例如 :
  1. val text = """在原始字串中,你不用跳脫字元,  
  2.               |所以可以直接在原始字串中寫下"  
  3.               |、\符號,不用特別跳脫"、\符號...""".stripMargin  
  4. println(text)  
程式執行後會顯示 :

如果你熟悉 Java,對於字串的特性應該知道,直接在""中寫下字串,只要字元內容相同,無論出現幾次,在JVM中只會有一個字串實例,而 == 是用於比較兩個物件參考是否相同,所以下面這個 Java 程式結果是熟悉Java的程式設計人員都知道的事 :
  1. String str1 = "Java";  
  2. String str2 = "Java"  
  3. String str3 = new String(str1);  
  4. System.out.println(str1 == str2); // 顯示 true  
  5. System.out.println(str1 == str3); // 顯示 false  
  6. System.out.println(str1.equals(str3)); // 顯示 true  
先前說過,在Scala中重用了 java.lang.String,也許你會認為以下的程式也會顯示true、false、true,不過結果可能會令你訝異 :
  1. val str1 = "Scala"  
  2. val str2 = "Scala"  
  3. val str3 = new String(str1)  
  4. println(str1 == str2)       // 顯示 true  
  5. println(str1 == str3)       // 顯示 true  
  6. println(str1.equals(str3))  // 顯示 true  
這是因為==在 Scala 中,是比較物件實質內容是否相同,這點與Java並不同,也因此第二個顯示會是true,在 Scala 中基本上也沒有必要直接呼叫 equals 方法,而可以直接使用 ==取代(之後會介紹,在 Scala 中,若要定義物件實質相等性,也是重新定義 equals() 方法,因為 == 會呼叫 equals() 方法). 如果你真的要比較兩個物件參考是否相同,可以使用 eq 或 ne 方法,例如 :
  1. val str1 = "Scala"  
  2. val str2 = "Scala"  
  3. val str3 = new String(str1)  
  4. println(str1 eq str2)         // 顯示 true  
  5. println(str1 eq str3)         // 顯示 false  
  6. println(str1 == str3)         // 顯示 true  
補充說明 :
Tutorialspoint - Scala Strings
[ Java 小學堂 ] Java 世界裡 equals 與 == 的差別

This message was edited 26 times. Last update was at 21/04/2016 12:35:32

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!