iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 12
0
Software Development

新手也能懂的 Kotlin Collection 賞玩門道系列 第 12

第十二天:Collection 操作之修改

上一章我們討論的都是如何「讀取」 Collection 裡的元素,不過更多時候我們需要「修改」Collection 裡的內容,也就是如何新增元素到 Collection 裡、怎麼移除 Collection 裡指定的元素、該怎樣更新 Collection 裡的元素等。不過要特別注意的是,因為這個章節裡討論的都會改變 Collection 的大小或內容,所以大多數的操作都是基於 Mutable 的 List,少部份也適用於 Set 及 Map。

新增元素

Collection 新增元素的 API 命名很直覺,就是 add(element),然後把要放進 Collection 的 element 當參數傳入即可,傳入的 element 預設就放到 Collection 的最後一格。若是想要指定要放到 Collection 的哪一格,則可以改用 add(index, element) 指定 element 要放置的 index 為何。

val mutableListOfNumbers = mutableListOf(1, 3, 5, 6, 7)
mutableListOfNumbers.add(8) // [1, 3, 5, 6, 7, 8]
mutableListOfNumbers.add(6, 999) // [1, 3, 5, 999, 6, 7, 8]

不過在指定 index 時,也要注意別超出邊界,不然執行時會拋出 IndexOutOfBoundsException 喔!假如一次想要增加很多個 element 的話,可以用 addAll(elements),傳入一個 Collection 參數即可,若有需要一樣可以用 addAll(index, elements) 指定插入位置。

val mutableListOfNumbers = mutableListOf(1, 3, 5, 6, 7)
mutableListOfNumbers.addAll(listOf(2, 4, 9)) // [1, 3, 5, 6, 7, 2, 4, 9]
mutableListOfNumbers.addAll(0, listOf(2, 4, 9)) // [20, 40, 90, 1, 3, 5, 6, 7, 2, 4, 9]

一個比較特別的寫法是用 += 來新增元素,作用跟 add(element)addAll(element) 一樣,都是將元素新增在 Collection 最後。

val mutableListOfNames = mutableListOf("Eli", "Mordoc", "Sophie")
mutableListOfNames += "Reginald" // [Eli, Mordoc, Sophie, Reginald]
mutableListOfNames += listOf("Alex", "Shruti") // [Eli, Mordoc, Sophie, Reginald, Alex, Shruti]

更新元素

操作 Collection 時大多會以 index 來指定位置,所以可以很直覺得用 [index] 來指定要更新哪個位置的元素,Kotlin 也有提供像 set(index, element) 這種型式的 API 供我們使用,傳入要更新的 index 位置及更新的內容即可。不過一樣要注意 index 是否有越界的問題,以免程式拋出例外。

val mutableListOfNumbers = mutableListOf(1, 3, 5, 6, 7)
mutableListOfNumbers[0] = 100 // [100, 3, 5, 6, 7]
mutableListOfNumbers.set(1, 200) // [100, 200, 5, 6, 7]

Collection 還提供了 replaceAll() 這個 API,你可以傳入一個 Lambda 來更新所有的元素內容。

val mutableListOfNumbers = mutableListOf(1, 3, 5, 6, 7)
// mutableListOfNumbers.replaceAll() // 還不會用…
mutableListOfNumbers.replaceAll{ it * 2 } // [2, 6, 10, 12, 14]

刪除元素

要刪除 Collection 內的元素,Kotlin 提供了非常多種 API 供不同情境下使用。開頭是 remove 的 API 就有數個,remove(element) 是用 element 來尋找後刪除、removeAt(index) 則是用 index 來尋找後刪除。

val mutableListOfNumbers = mutableListOf(1, 3, 5, 6, 7)
mutableListOfNumbers.remove(3) // [1, 5, 6, 7]
mutableListOfNumbers.removeAt(0) // [5, 6, 7]

Kotlin 的標準函式庫也提供 removeFirst()removeLast() 來刪除 Collection 的第一個或最後一個元素並回傳。另外,考量到 Collection 有可能是空的,也有對應的 removeFirstOrNull()removeLastOrNull() 會在 Collection 是空的時候不觸發 Exception 而是回傳 null。

val shopping = mutableListOf("Tea", "Eggs", "Sugar")
val first = shopping.removeFirst()
// shopping 是 [Eggs, Sugar]
// first 是 Tea

val emptyShoppingList = mutableListOf<String>()
val first = emptyShoppingList.removeFirstOrNull()
// emptyShoppingList 是 []
// first 是 null

val shopping = mutableListOf("Tea", "Eggs", "Sugar")
val last = shopping.removeLast()
// shopping 是 [Tea, Eggs]
// last 是 Sugar

val emptyShoppingList = mutableListOf<String>()
val last = emptyShoppingList.removeLastOrNull()
// emptyShoppingList 是 []
// last 是 null

若是要刪除 Collection 內數個元素,可以用 removeAll(elements)、若是反過來要「保留」某些元素的話,則可以用 retainAll(elements)

val shopping = mutableListOf("Tea", "Eggs", "Sugar")
shopping.removeAll(listOf("Milk", "Sugar")) // [Tea, Eggs]

val anotherShopping = mutableListOf("Tea", "Eggs", "Sugar")
anotherShopping.retainAll(listOf("Tea", "Sugar") // [Tea, Sugar]

順帶一提,Collection 也支援 -= 刪除元素運算子,用來刪除 Collection 的某個元素,或從清單刪除 Collection 所列元素。依不同情境,用法如同 remove()removeAll()

mutableListOf("Eli", "Mordoc", "Sophie") -= "Eli"
// ["Mordoc", "Sophie"]

val listOfNames = mutableListOf("Eli", "Mordoc", "Sophie")
listOfNames -= listOf("Eli", "Mordoc")
// ["Sophie"]

在刪除元素的過程中,也可以設定一些「條件」,比方說 removeIf()removeAll()retainAll() 可以傳入一個 Lambda,這個 Lambda 裡帶著一個判斷邏輯,結果是 true 的就會被移除。

val listOfNames = mutableListOf("Eli", "Mordoc", "Sophie")
listOfNames.removeIf { it.contains("o") }
// [Eli]

val shopping = mutableListOf("Tea", "Eggs", "Sugar")
shopping.removeAll { it.contains('g') }
// [Tea]

val anotherShopping = mutableListOf("Tea", "Eggs", "Sugar")
anotherShopping.retainAll { it.contains('g') }
// [Eggs, Sugar]

當然,你也可以開大絕,直接用 clear() 清空整個 Collection!

val mutableListOfNumbers = mutableListOf(1, 3, 5, 6, 7)
mutableListOfNumbers.clear()

表格整理

因為 Collection 橫跨 Array、List、Set、Map 等四種類別,不是所有 API 都能在每個類別上實作,在使用前務必要確定正在操作的這個類別是否有這個 API 可以使用,才不會發生預期之外的行為喔!以下用表格快速整理本篇文章裡提到的所有方式:

新增

行為 Array MutableList Set Map
+= 新增元素 x v v x
add(element) 新增元素 x v v x
add(index, element) 在指定位置新增元素 x v x x
addAll(elements) 新增多個元素 x v v x
addAll(index, elements) 在指定位置新增多個元素 x v x x

更新

行為 Array MutableList MutableSet MutableMap
[index] 更新指定位置的元素 v v x v
set(index, element) 更新指定位置的元素 v v x v
replaceAll{} 用 λ 取代元素 x v x v

刪除

行為 Array MutableList MutableSet MutableMap
-= 刪除一個或多個元素 x v v v
remove(element) 刪除指定元素 x v v v
removeAt(index) 刪除指定位置的元素 x v x x
removeAll(elements) 刪除指定的多個元素 x v v x
removeAll {} 用 λ 刪除元素 x v v x
removeIf {} 刪除 x v v x
retainAll(elements) 保留指定的多個元素 x v v x
retainAll{} 用 λ 保留元素 x v v x
removeFirst() 刪除第一個元素 x v x x
removeFirstOrNull() 刪除第一個元素,若元素是 empty 則回傳 null x v x x
removeLast() 刪除最後一個元素 x v x x
removeLastOrNull() 刪除最後一個元素,若元素是 empty 則回傳 null x v x x
clear() 清空 x v v v

參考資料


上一篇
第十一天:Collection 操作之取值
下一篇
第十三天:Collection 操作之截取
系列文
新手也能懂的 Kotlin Collection 賞玩門道31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言