「既然已經知道了interface
,就可以來看Collections
三大interface
——List
、Set
、Map
。和陣列Array
一樣,是放入多筆資料的資料結構,一開始就要選好是成員固定
還是成員可變動
的狀態。」
唯心在紙上將初始化的函式按照狀態歸類。
成員固定:listOf()
、mapOf()
和setOf()
。
成員可變動:mutableListOf()
、mutableMapOf()
和mutableSetOf()
。
「每種資料結構都有其特性:Array
不能改變長度,因為被宣告長度之後,會專門分配一塊連續的記憶體
;List
重視成員之間的順序
,所以可以用index
取得該位置的成員;Set
會馬上合併重複的成員,因此成員都是獨一無二
,但也因此不在乎成員之間的順序;Map
因為成員存放的位置比較複雜,會讓我們指定每個位置的key
來映射,所以可以用key
取得該位置的成員。」
「Collections
被學姐拿出來特別介紹,應該有特殊的地方囉?」得到貓咪的治癒後,詩憶以超出平常的敏銳發問。
「是的,Collections
提供各種好用的函式,之前需要寫迴圈才能做到的篩選,現在只需要呼叫filter
。雖然也可以再用一次之前飲料價錢的例子,不過老用同樣的篩選條件缺乏新鮮感呢⋯⋯」唯心沈吟了片刻才作出決定。「這次用品項名來篩選吧。利用判斷結尾字串的函式endsWith
來檢驗品項名,只保留奶茶系列的飲料。」
fun main() {
val drinks = listOf(Drink("奶茶", 50), Drink("綠奶茶", 30), Drink("可可", 40),
Drink("珍珠奶茶", 70))
val milkTeas = drinks.filter { it.name.endsWith("奶茶") }
println(milkTeas)
}
電腦在她的操作下印出[Drink(name=奶茶, price=50), Drink(name=綠奶茶, price=30), Drink(name=珍珠奶茶, price=70)]
的結果。
「現在我們再加上一個只要列出品項名的情境,比如請客提供的單子是不會附上價格的。這時可以用map
函式,雖然和Map
名字一樣,其實相同的只有映射動作,會把類別成員的品項名屬性拉出來,產生新的字串list
,然後再根據新list
去篩選。」
fun main() {
val drinks = listOf(Drink("奶茶", 50), Drink("綠奶茶", 30), Drink("可可", 40),
Drink("珍珠奶茶", 70))
val milkTeaNames = drinks.map(Drink::name).filter { it.endsWith("奶茶") }
println(milkTeaNames)
}
這次電腦果然只印出品項名[奶茶, 綠奶茶, 珍珠奶茶]
。
「如果只想請前兩種奶茶,可以用take
函式,只是這樣寫的話,程式還是篩選出全部的奶茶才輸出前兩種。現在是因為我一開始列出的飲料只有四筆,所以時間沒什麼影響。但如果飲料資料有上萬筆的話,會希望加快回報的效率,找到兩筆奶茶飲料就不繼續篩選後面的飲料。這時候就要利用asSequence()
轉成Sequences
類別,Sequences
類別的特性是一筆資料跑到終點才跑下一筆,而take(2)
的條件正在終點線內。這個特性還滿實用的,好好記住唷。」唯心遞出她的黃色螢光筆,詩憶接過後馬上在asSequence()
劃上深刻的重點線。
fun main() {
val drinks = listOf(Drink("奶茶", 50), Drink("綠奶茶", 30), Drink("可可", 40),
Drink("珍珠奶茶", 70))
val milkTeaNames2 = drinks.map(Drink::name).filter { it.endsWith("奶茶") } }.take(2)
val milkTeasNames2Seq = drinks.asSequence().map(Drink::name).filter { it.endsWith("奶茶") }.take(2) }
println(milkTeaNames2)
println(milkTeaNames2Seq.toList())
}