前面介紹的 Collection 類別裡,像 Array 或 List 都是以索引(index)做為取得元素的關鍵。但以數字為基礎的 index 雖然方便電腦做計算,但對人類來說缺乏語義也不易記憶。在操作資料的時候,有時會需要以鍵(Key)值(Value)對照的方式來儲存,這時我們就需要使用 Map
。
Map
是 Kotlin 另一種常用的 Collection 類別,它是一個承裝由開發者定義的鍵值對的集合。它有幾個重要的特點:
宣告 Map 很簡單,Kotlin 標準函式庫提供了兩個函數 mapOf()
用來宣告一個靜態的 Map、mutableMapOf()
用來宣告一個動態的 Map。
val mapOfFruit = mapOf("Apple" to 7, "Banana" to 5, "Orange" to 7)
val mutableMapOfFruit = mutableMapOf("Apple" to 7, "Banana" to 5, "Orange" to 7)
透過 Kotlin 的型別推斷,mapOfFruit
的型別就會是 Map<String, Int>
、mutableMapOfFruit
的型別則會是 MutableMap<String, Int>
。這邊要注意的是,為了定義 Key 與 Value 的組合,中間使用 to
連接。這個 to
看起來很像程式語言的保留字,但實際上它是一個 infix
Function,在 Kotlin 裡,infix Function 在使用時,可以省略 .
及 ()
等呼叫函數的符號。to
函數將它左邊和右邊的值合併成一個 Pair
,也就是說,上面的程式碼可以寫成下面這樣:
val setOfFruit = mapOf(
Pair("Apple", 7),
Pair("Banana", 5),
Pair("Orange", 7)
)
val mutableMapOfFruit = mutableMapOf(
Pair("Apple", 7),
Pair("Banana", 5),
Pair("Orange", 7)
)
假如你今天需要宣告一個空的 Map,則有幾種可行的作法:
val emptyMap = mapOf<String, Int>() // 型別是 Map<String, Int>
val mutableEmptyMap = mutableMapOf<String, Int>() // 型別是 MutableMap<String, Int>
val emptyMapByEmptyMap = emptyMap<String, Int>() // 型別是 Map<String, Int>
當我們把資料放進 Map 後,我們可以用 Key 或是迴圈來取得其中的資料:
val mapOfFruit = mapOf("Apple" to 7, "Banana" to 5, "Orange" to 7)
val price = mapOfFruit["Apple"] // 取得 Key 是 Apple 的值
for (fruit in mapOfFruit) {
println("${fruit.key} (${fruit.value})")
// 會依序印出
// Apple (3)
// Banana (5)
// Orange (7)
}
我們也可以用 Map 的屬性或方法來取得 Map 的資訊,或是做資料處理:
val mapOfFruit = mapOf("Apple" to 3, "Banana" to 5, "Orange" to 7)
val size = mapOfFruit.size // 以屬性取得 Map 的大小
val count = mapOfFruit.count() // 以方法取得 Map 的大小
val keys = mapOfFruit.keys // 以屬性取得 Map 的所有 Key
val value = mapOfFruit.values // 以屬性取得 Map 的所有 Value
不過因為 Map 的資料結構相對彈性,會以什麼型別當 Key、裡面會被什麼 Value 都有可能,所以有些 Array、List、Set 身上有的方法在 Map 上就不見得存在,這點要稍為注意一下!
有別於 Collection 裡的其他類別,Map 就是一個對照表(Lookup Table)的結構,或是在有些程式語言裡稱為 Dictionary
。以上介紹的 Kotlin Collection 類別各有特色,一開始學習時往往眼花撩亂,要記得抓緊每個類別最重要的特性,才能在最適合的時機使用正確的類別。後續的章節也會針對 Collection 之間的差異做比較,並提示在哪些情境下適合用哪種 Collection 的技巧。