Kotlin學習筆記(6) — 字串、數字

Andy Lu
11 min readAug 17, 2020

字串、數字在任何程式語言中都是屬於基本類別,因 Kotlin 可以與 Java 互相操作,所以在這兩種基本類別中,都能看到 Java 的影子,但是透過 lambda ,許多函數變得更加簡單。這也是新語言的優勢之一吧。

字串 (String)

字串,其實就是一連串的字元所組成的。定義一個字串之後,就會在記憶體中規劃了一塊空間存放。每次的修改都不會影響到已經實例化的字串。

定義字串

Kotlin 有兩種定義字串的方式:

  1. 使用 ""雙引號將文字包起來。
  2. 使用三個 """ 雙引號將文字包起來。

例如:

val oneLine = "This is one line string. \\n"
val twoLine = """
This is first line of the two lines string
This is second line of the two lines string
"""

加號

可以使用加號 + 將兩段文字接起來,加號左右只要有一邊為字串,則輸出就會為字串。

如下:

val item10 = "Item" + 10
println(item10)
//Item10

樣板字串 (String Template)

包含表示式 (Expressions) 的字串。

  • 在字串中用錢字號開頭 $ 取用字串。
val a = "abc"
println("String is $a")
//String is abc

也可以使用錢字號 $ 加上大括弧 {} 呼叫函式,如此會將函式的結果轉換成字串。

val b = "def"
println("Length of b is ${b.length}")
//Length of b is 3

indexOf

indexOf 會回傳第一個符合傳入的字元的位置,如果找不到,則會回傳 -1。

val item ="Item\\n"
println(item.indexOf('a'))
//-1
println(item.indexOf('t'))
//1
  1. index 由 0 開始算。
  2. \n為換行,其中 \ 為跳脫字元。

跳脫字元

跳脫字元是用來處理在文字中的特殊字元。

常用跳脫字元,如下表:

substring

將原字串根據 substring 的引數,產生一個新的字串

val index = 3
val abcedf = "abcdef".substring(0 until index)
//abc
  1. substring 支援 IntRange。
  2. 可以利用 until 產生 Range (例如: 0 until index),until 建立的範圍不包含上限值。
val index = 3
val abcedf = "abcdef".substring(0 .. index)
//abcd
  • 也可以利用 .. 產生 IntRange範圍包含上限值。

split

將分割的引數 (字元) 帶入 split 中,字串將會根據 split 帶入的字元返回一個 字串結果集合。

val menuData = "shandy,Dragon's Breath,5.91"
val data = menuData.split(',')
val type = data[0] // shandy
val name = data[1] // Dragon's Breath
val price = data[2] // 5.91

解構 (destructuring)

  • Kotlin 允許在一個運算式設定多個變數的值。
  • 只要是集合結果,都能使用解構指派值。
  • 如果變數的數量大於解構的數量,將會拋出IndexOutOfBoundsException。
val (type, name, price) = menuData.split(',')

replace

private fun toDragonSpeak(phrase: String)=
phrase.replace(Regex("aeiou")){
when (it.value) {
"a" -> "4"
"e" -> "3"
"i" -> "1"
"o" -> "0"
"u" -> "|_|"
else -> it.value
}
}
  • replace 函數要求兩個引述,第一個是正規表示式 (regex),用來決定要替換哪些字元。第二個引數是匿名函數,用來確定該如何替換搜尋到的字元。

不可變字串

  • 不管是用 var 或是 val 宣告,Kotlin 的所有字串都是不可變的。如果一個字串變數宣告為 var 變數,即使可以指派新值,原字串實例本身也不會改變。

字串比較

if(name == "Dragon's Breath")
  • 利用結構相等運算子 ==,判斷 name 變數值和 “Dragon’s Breath” 是否結構相等
  • === 是用來判斷參照相等,會檢查兩個變數是否引用同一個類別實例,也就是說,兩個變數是否指向記憶體的同一個物件。
  • 補充:Java 比較字串是使用 equals函數

Unicode

利用跳脫字元 \u 加上 Unicode 。

val omsymbol = '\\u0950'
println(omsymbol)
//ॐ

forEach

字串可以使用 forEach 來走訪字串中的每一個字元。

"Dragon's Breath".forEach{
println("$it\\n")
}
/*
D
r
a
g
o
n
'
s

B
r
e
a
t
h
*/

小記

  1. 定義字串使用 "字串"""" 字串 """ ,前者為一般定義字串的方式,後者則是定義較長的字串。
  2. 文字串接可以使用 + 或是使用樣板字串(String template)
  3. indexOf() 回傳第一個搜尋到的指定字元位置。位置由0開始計算,找不到則回傳 -1 。
  4. substring()將整數範圍帶入,可以產生一組包含在元字串內的子字串。
  5. 可以使用 until 關鍵字產生整數範圍 (不包含上限值),也可以使用 .. (包含上限值)
  6. split 產生字串集合,也可以直接使用解構方式儲存多個變數。
  7. Kotlin 中,所有定義的字串皆為不可變的字串,不管是 val 或是 var 。當 var修改字串後,會產生一組新的字串,而不是修改原本的以實例 (Instance) 的字串。
  8. 利用 == 比較字串。
  9. 利用 forEach 走訪字串中每一個字元。

數字

Kotlin 與 Java 相同數字類型都有符號 (Signed),意思是能表示正數以及負數,分為兩類:

  1. 整數 (Integer),依據不同的大小,可以分為四種型別。

定義變數的時候,如果沒有超過 Int 的最大值,則 Kotlin 會自動推斷成 Int

一般來說,不需要使用到 Byte 以及 Short;Byte 與 Short 一般都是使用在與 Java 互動的程式碼上。

2. 浮點數 (Floating Point Number):Kotlin 提供兩種浮點數類別。
定義浮點數時,預設都是為 Double ,可以在數字的後方加上 f ,定義該變數為 Float

val pi = 3.14               //Double
val e = 2.71828 //Double
val eFloat = 2.7182818284f //Float, actual value is 2.7182817
Floating point number bit diagram

字串轉成數字類別

Kotline 提供了有用的函數,可以將字串轉換成包括數字的其他類別。

常用的轉換函數如下:

  • toFloat:轉成浮點數 Float
  • toFloatOrNull:轉成浮點數 Float 或是 null
  • toDouble:轉成浮點數 Double
  • toDoubleOrNull:轉成浮點數 Double 或是 null
  • toInt:轉成整數
  • toIntOrNull:轉成整數 Int 或是 null
  • toLong:轉成整數 Long
  • toBigDecimal:轉成 BigDecimal
  • 嘗試轉換格式錯誤的字串會拋出異常(NumberFormatException)。
  • 使用 toXXXOrNull() ,當字串無法轉換時,會回傳 null 而不是拋出異常。
println("100.9".toInt())
//java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
println("100.9".toIntOrNull())
//null
  • 亦可以使用空合併運算子 (?:) 與 toXXXOrNull()合併使用
println("100.9".toIntOrNull() ?: 0)
//0

Int 類型轉成 Double 類型

val playerSliver = 110 //Int
val playerGold = 3
val totalPurse = playerGold + (playerSliver / 100.0)
println(totalPurse)
// 4.1

Kotlin 在做運算時,如果參與運算的兩個數字都是整數類型,那麼結果也會是整數類型(小數點被忽略),若其中一個數字是浮點數,則 Kotlin 就會採用浮點數運算。如上 playerSliver / 100.0 = 11.0

格式化 Double 類型

val totalPurse = 10.1
val price = 5.91
val remainingBalance = totalPurse - price
//未格式化 Double 類型
println(remainingBalance)
//4.1899999999999995
// 格式化 Double 類型
print("%.2f".format(remainingBalance))
//4.19

在電腦運算中,因為採用 Double 類型計算,所以結果是實數的近似值 (4.1899999999999995)。利用 format 函數可以將不需要的小數點位數處理掉,在 format 前方的 "%.2f"表示把浮點數四捨五入至兩位小數。

Double 類型轉成 Int 類型

  • toInt()
val totalPurse = 10.1
val totalPurseInt = totalPurse.toInt()
println(totalPurseInt)
//10

Double 提供了 toInt() 函數來轉換成 Int 整數,Double 類型經過 toInt() 轉換之後,因為要存進整數內,所以小數點的部分被截掉,這稱為精度損失

位元運算

電腦計算都是將數值轉換成二進位來計算,Integer 也提供了利用二進位來計算的方式。因為電腦計算就是以二進位來計算,所以當以二進位來做運算時,速度會比較快。

下表為常用的位元運算:

無符號數?

在 Kotlin 1.3 版之後,Kotlin 正在測試無符號數,意指沒有欄位儲存符號,所以沒有負數。

少了符號,意指可以多使用 1 bit ,跟有符號數相比,最大值多了一倍。

不過,因為還沒有正式釋出,所以使用的時候會出現警告訊息。

小結

  1. Kotlin 的數字系統為有符號數,分為兩種類別:整數、浮點數。
  2. 整數又可分為:Byte、Short、Int 以及 Long。
  3. 浮點數可分為:Float 以及 Double。
  4. 定義整數時,若無指定類型,預設為 Int,若大於 Int 的最大值,則為 Long。
  5. 定義浮點數時,若無指定類型,預設為 Double ,在數字後面加上 f ,可以將此變數定義為 Float。
  6. 運算時,若運算元的數值皆為整數,結果會為整數;反之,若有一個數值為浮點數,則產生的結果為浮點數。
  7. 浮點數轉換成整數時,需注意精度損失的情況。

若這篇文章有幫助到你,點擊拍手,給我鼓勵。

謝謝

參考

Kotlin 權威2.0:Android 專家養成術 — 第七章:字串

Kotlin 權威2.0:Android 專家養成術 — 第八章:數字

KotlinLang.org: Basic-types-Strings

KotlinLang.org: Destructuring Declarations

KotlinLang.org: Basic-types-Numbers

--

--

Andy Lu

Android/Flutter developer, Kotlin Expert, like to learn and share.