Kotlin 學習筆記(8)-集合函數
目錄
1. List
2. MutableList
3. Set
4. MutableSet
5. Map
6. MutableMap
集合函數 (Collection) 是一種儲存一連串物件的方法,集合函數的繼承關係圖如下:
主要有三個類別:
- List:可儲存重複值,用索引值 (Index) 取值,為有序排列。
- Set:儲存在
Set
的內容都是唯一的,為無序排列。 - Map*:採用 Key-Value 的方式儲存,用 Key 可以取得 Value。
註:Map 雖然不是繼承 Collection,但仍歸納於集合函數內。
上面三個類別都是不可修改內容的,也就是說當 List
Set
Map
建立出來之後,就無法修改其內容了。但是,個別有一個可以繼承原類型可修改的類型:
- MutableList:可修改的 List。
- MutableSet:可修改的 Set。
- MutableMap:可修改的Map。
List
可以儲存非重複項,每一個儲存在 List
的項目 (Element) 都含有一個 Index,Index 作為排序使用。
建立 List
listOf()
:可以產生一組List
。
val nameList: List<String> = listOf("Eli", "Mordoc", "Sophie")
- 類型推斷:因為
listOf
裡面已經有內容,Kotlin 編譯器會自動判斷型別,所以可以將變數名稱後方的型別刪除。
val nameList = listOf("Eli", "Mordoc", "Sophie")
取值
[Index]
: 利用中括弧加上索引值 (Index),即可快速地取得該位置的內容,需要注意的是,如果索引值的數值比 List 還大,就會拋出ArrayIndexOutOfBoundsException
。first()
:可取得 List 第一個項目的值。last()
:可取得 List 最後一個項目的值。
val nameList = listOf("Eli", "Mordoc", "Sophie")
nameList[0] // Eli
nameList.first() // Eli
nameList.last() // Sophie
nameList[3] // ArrayIndexOutOfBoundsException
用中括弧取值,如果使用錯誤的索引值,會發生例外,Kotlin 提供了安全取值的方法:
getOrElse
:取值,若取不到值,則回傳 Lambda 函式的回傳值。getOrNull
:取值,若取不到值,則回傳 null。
val forthName = nameList1.getOrElse(4) {"Not Found"}
// Not Foundval forthName = nameList1.getOrNull(4)
// Nullval forthName = nameList1.getOrNull(4) ?: "Not Found"
// Not Found
查詢內容是否存在
contains()
: 代入一個欲查詢的項目,若存在則回傳true
;反之,回傳false
。containsAll()
: 代入一個欲查詢的集合,若存在則回傳true
;反之,回傳false
。
nameList.contains("Eli") // true
nameList.contains("Andy") // falsenameList.containsAll(listOf("Sophie", "Mordoc")) //True
MutableList
- 繼承
List
,增加了寫入的操作。
建立 MutableList
mutableListOf()
:快速的建立可變 List,可以給予初始值,或是之後增加。- 如果給予初始值,Kotlin 會自動判斷型別。
val mutableList = mutableListOf("Tiger", "Lion", "Penguin")
- 無給予初始值,無法自動判斷型,須提供型別,有下列兩種方式提供:
val mutableList = mutableLisOf<String>()val mutableList: MutableList<String> = mutableListOf()
修改內容
add(Element)
: 在 List 的尾端加入 Element。add(Index, Element)
:在指定的 Index 加入 Element,Index 最大範圍為 List 的 大小。remove(Element)
:刪除 List 中的 Element 。removeAt(Index)
:刪除指定索引值的項目。+= Element
: 在 List 的尾端加入 Element,與add(Element)
功能相同。[Index]=Updated Element
:將指定位置的 Element 更改為 Updated Element。clear()
:清除 List 所有的項目。
val mutableList = mutableListOf("Tiger", "Lion", "Penguin") mutableList.add("Eagle") //[Tiger, Lion, Penguin, Eagle]
mutableList.remove("Tiger") //[Lion, Penguin, Eagle]mutableList.removeAt(0) //[Penguin, Eagle]mutableList.add(0, "Tiger") //[Tiger, Penguin, Eagle]mutableList += "Jagar" //[Tiger, Penguin, Eagle, Jagar]mutableList[0] = "Lion" //[Lion, Penguin, Eagle, Jagar]mutableList.clear() // []
Set
- 儲存在
Set
中的項目,都是唯一的,而且沒有順序。
建立 Set
- 如同 List 類有
listOf
,Set 類也有setOf
。
例:
val weekday = setOf("Monday", "Tuesday", "Wednesday", "Thursday", "Friday")
// [Monday, Tuesday, Wednesday, Thursday, Friday]
val weekday = setOf("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Friday")
// [Monday, Tuesday, Wednesday, Thursday, Friday]
- 上例可以發現,第二個
setOf
定義了兩個 Friday,但是結果卻只有一個 Friday 存在Set
中。
查詢內容是否存在
contains()
: 代入一個欲查詢的項目,若存在則回傳true
;反之,回傳false
。containsAll()
: 代入一個欲查詢的集合,若存在則回傳true
;反之,回傳false
。
查詢特定位置的值
- 前面提到,
Set
沒有順序,所以查詢特定位置的值,Set
會走訪每一個項目找到值。 elementAt(n)
:可以取得第n個存入set
的項目。
MutableSet
- MutableSet 繼承 Set,加上寫入的動作。
新增項目函數
add()
:新增一個項目。addAll()
:新增多個項目。+=
:新增一個項目。
刪除項目函數
remove()
:刪除一個項目。removeAll()
:刪除多個項目。-=
:刪除一個項目。clear()
:清除所有項目。
distinct( ) = toSet( ) + toList( )
- List 存放項目時會加上 index,藉由 index 可以快速的找到項目。
- Set 存放唯一的項目,但是找尋項目比較慢。
兩種集合函數都有不同的用途,如果需要一個具有存放唯一值的 List,我們可以使用 toSet()
將 List 轉換成 Set,轉換之後重複的項目就會被刪除,接者使用 toList()
,則可以將 Set 在轉換成 List ,如此,就能擁有一個存放唯一值的 List。
Kotlin 在 List 函數中提供了另一個函數 distinct()
來簡化 toSet().toList()
的動作,直接將 List 中重複的項目移除。
val items = listOf("Pen", "Pen", "Eraser").distinct()
//[Pen, Eraser]
迭代 (Iterator)
文章一開始的繼承關係圖,顯示 Collection 是繼承 Iterator ,那麼繼承 Collection 的 List 以及 Set 自然也有迭代的功能。
如何迭代?
方法1:
for
for(SINGLE_ITEM in COLLECTION)
: for 函數,括弧中間使用 in
關鍵字, in
左方擺放每一個讀出來的項目,右方擺放集合函數(Ex: List)
val animals = listOf("Pig", "Chicken", "OX")//Method: for for(animal in animals){
println("Here has $animal")
}
//Here has Pig
//Here has Chicken
//Here has OX
方法2:
forEach
在每個集合函數,都有包含 forEach
函數,使用方法如下。
在 forEach
後方代入 Lambda 函數,在 Lamba 函數中,用 it
代表,每一次迭代中的值。
val animals = listOf("Pig", "Chicken", "OX")
//Method: forEach animals.forEach {
println("Here has $it")
}
//Here has Pig
//Here has Chicken
//Here has OX
Map
介紹完 List
與 Map
之後,集合函數第三個就是 Map
了。
- Map 是用 Key-Value 來儲存資料。一個 Key 對應到一個 Value,Key 不可重複,Value 可以重複。
建立一個Map
同樣地,Map 也有一個 mapOf 函數。
val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3)
- 在
mapOf
裡,擺放的是 Key-Value,Kotlin 提供的一個直覺的寫法:KEY to VALUE
,用關鍵字to
定義一組 Key-Value。 - 另外,還可以使用
Pair(KEY, VALUE)
的形式來定義 Key-Value。
val val numbersMap = mapOf(
Pair("key1", 1),
Pair("key2", 2),
Pair("key3", 3) )
讀取資料
[KEY]
:回傳 Key 對應的值,若不存在則回傳 null。getValue
:回傳 Key 對應的值,若不存在則拋出例外 (NoSuchElementException)。getOrElse
:回傳 Key 對應的值,若不存在則用 Else lambda 取值。getOrDefault
:回傳 Key 對應的值,若不存在則回傳 Default 值。
val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3) numbersMap["key1"] // 1 numbersMap.getValue("key4") // NoSuchElementException numbersMap.getOrElse("key4") { 0 } // 0 numbersMap.getOrDefault("key4", 0 ) //0
MutableMap
- MutableMap 繼承 Map,加上寫入的動作。
修改資料
[KEY]=Value
:若 Key 存在,更新原本的值,若 Key 不存在,新增一組 Key-Value。+=
:同上。putAll(COLLECTION)
:以 Collection 類傳入,可同時加入多組 Key-Value。remove(KEY)
:若 Key 存在,則把該組 Key-Value 移除,並且回傳這個 Value;反之,若不存在,則回傳 null。- KEY
:若 Key 存在,則將 Key-Value 直接移除;反之,不移除任何項目,結束後回傳原Map。
結論
洋洋灑灑寫了一大篇,介紹了三種不同類型的集合函數,分別有各自的使用情境。
這邊歸納一下:
List :可以存放包含索引值的重複項目,可以快速的取值;
Set:存放不重複項,因內部實作方式,取值速度慢;
Map:存放 Key-Value 組合的數值,適合用在有對應關係的數值。
如果這篇文章有幫助到你,請拍手鼓勵我吧。
謝謝收看。
參考
Kotlinlang.org: Collections
Kotlin 權威2.0:Android 專家養成術 — 第十章、第十一章:List、Set 以及 Map