SlideShare a Scribd company logo
1 of 72
Download to read offline
Chapter 8: Efficient collection processing
Effective otlin 讀書會
范聖佑
JetBrains
Developer Advocate
2022/12/08 導讀
第八章:有效率的 Collection 操作
—
• Collection 幾乎無所不在
• Collection 操作是 Functional Programming 裡最重要的功能
• Collection 操作最佳化在⼤型且在意效能的系統裡特別重要
• 好消息!Collection 操作最佳化並不難,只需掌握幾個原則即可!
討論主題
—
• 主題 51:傾向使⽤ Sequences 來取代巨量且有多次操作⾏為的 Collection
• 主題 52:考慮使⽤ Map 來儲存關聯的元素
• 主題 53:考慮使⽤ groupingBy 來取代 groupBy
• 主題 54:限制操作的數量
• 主題 55:(有效能考量時) 使⽤ Primitive Array 來操作資料
• 主題 56:考慮使⽤ Mutable Collection
主題 51
傾向使⽤ Sequences 來取代巨量且有多次
操作⾏為的 Collection
Iterable 與 Sequence 的差異
—
• Iterable
- 每⼀步都回傳⼀個新的 Collection
- 積極的 (Eager),每⼀步都會觸發運算
• Sequence
- 每⼀步都回傳⼀個新的 Sequence
- 懶惰的 (Lazy),除非有結束型操作才會開始運算
Sequence 的惰性帶來的好處
—
• 操作時依⾃然順序執⾏
• 只做最少量的操作
• 可以無限⼤
• 不需要在每⼀步都產⽣新的 Collection
操作時依⾃然順序執⾏
—
• Sequence 的運算順序符合⾃然邏輯
預測⼀下兩者間的
操作順序?
—
sequenceOf(1, 2, 3)
.filter { print("F$it, "); it % 2 !" 1 }
.map { print("M$it, "); it * 2 }
.forEach { print("E$it, ") }
listOf(1, 2, 3)
.filter { print("F$it, "); it % 2 !" 1 }
.map { print("M$it, "); it * 2 }
.forEach { print("E$it, ") }
sequenceOf(1, 2, 3)
.filter { print("F$it, "); it % 2 !" 1 }
.map { print("M$it, "); it * 2 }
.forEach { print("E$it, ") }
!" Prints: F1, M1, E2, F2, F3, M3, E6,
listOf(1, 2, 3)
.filter { print("F$it, "); it % 2 !" 1 }
.map { print("M$it, "); it * 2 }
.forEach { print("E$it, ") }
!" Prints: F1, F2, F3, M1, M3, E2, E6,
預測⼀下兩者間的
操作順序?
—
不⽤ Collection 時
—
for (e in listOf(1, 2, 3)) {
print("F$e, ")
if (e % 2 !" 1) {
print("M$e, ")
val mapped = e * 2
print ("E$mapped, ")
}
}
!" Prints: F1, M1, E2, F2, F3, M3, E6,
只做最少量的操作
—
• 不做多餘事 (懶惰⾄上)
誰的動作比較少?
—
(1!#10)
.filter { print("F$it, "); it % 2 !" 1 }
.map { print("M$it, "); it * 2 }
.find { it > 5 }
(1!#10).asSequence()
.filter { print("F$it, "); it % 2 !" 1 }
.map { print("M$it, "); it * 2 }
.find { it > 5 }
誰的動作比較少?
—
(1!#10)
.filter { print("F$it, "); it % 2 !" 1 }
.map { print("M$it, "); it * 2 }
.find { it > 5 }
!" Prints: F1, F2, F3, F4, F5, F6, F7, F8,
!" F9, F10, M1, M3, M5, M7, M9,
(1!#10).asSequence()
.filter { print("F$it, "); it % 2 !" 1 }
.map { print("M$it, "); it * 2 }
.find { it > 5 }
!" Prints: F1, M1, F2, F3, M3,
官網 Iterable 範例
—
val words = "The quick brown fox jumps over the lazy dog"
.split(" ")
val lengthsList =
words.filter {
it.length > 3
}.map {
it.length
}.take(4)
println("Lengths of first 4 words longer than 3 chars:")
println(lengthsList)
官網 Sequence 範例
—
val words = "The quick brown fox jumps over the lazy dog"
.split(" ")
val wordsSequence = words.asSequence()
val lengthsSequence =
wordsSequence.filter {
it.length > 3
}.map {
it.length
}.take(4)
println("Lengths of first 4 words longer than 3 chars")
println(lengthsSequence.toList())
可以無限⼤
—
• 可⽤ generateSequence() 或 sequence() 產⽣無限⼤
的 Sequence
• ⼀定要⽤結束型操作 (如 take()、first()、find()、
indexOf()…等) 才可取回
• 注意!⽤ any()、all()、none() 前⼀定要有結束型操
作,以免進入無窮迴圈
產⽣ Sequence
opt.1
—
generateSequence(1) { it + 1 }
.map { it * 2 }
.take(10)
.forEach { print("$it, ") }
!" Prints: 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
產⽣ Sequence
opt.2
—
val fibonacci: Sequence<BigDecimal> = sequence {
var current = 1.toBigDecimal()
var prev = 1.toBigDecimal()
yield(prev)
while (true) {
yield(current)
val temp = prev
prev = current
current += temp
}
}
print(fibonacci.take(10).toList())
!" Prints: [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
不需要在每⼀步都產⽣新的 Collection
—
• ⼩量的時候感覺不出來,處理⼤型檔案時就很有感
什麼時候會產⽣
新的 Collection?
—
numbers
.filter { it % 10 !" 0 } !" 1 collection here
.map { it * 2 } !" 1 collection here
.sum()
!" In total, 2 collections created under the hood
numbers
.asSequence()
.filter { it % 10 !" 0 }
.map { it * 2 }
.sum()
!" No collections created
⼤檔案比較
—
File("!!$").readLines()
.drop(1) !" Drop descriptions of the columns
.mapNotNull { it.split(",").getOrNull(6) }
!" Find description
.filter { "CANNABIS" in it }
.count()
.let(!%println)
File("!!$").useLines { lines: Sequence<String> !"
lines.drop(1) !" Drop descriptions of the columns
.mapNotNull { it.split(",").getOrNull(6) }
!" Find description
.filter { "CANNABIS" in it }
.count()
.let { println(it) }
}
「傾向使⽤ Sequences 來取代巨量且有多次操作⾏為的 Collection 」
這句話到底是什麼意思?
—
• 多⼤叫巨量?
- 上萬筆以上的資料
- 元素本⾝就好幾 MB
• 多少次叫多次?
- 超過⼀次
- 依據數量級的不同才會有感
什麼時候 Sequence 會不快?
—
• 當使⽤ sorted() 的時候
- 還是得把整個 Collection 跑⼀遍 (底層有做⼀些轉換)
- 無法⽤在無限⼤的 Sequence 上
- 但在⼤部份的情況下還是可能比 Collection 快⼀點
怎麼看 Java Stream?
—
• Kotlin 的函式比較多且語法比較好⽤
• Kotlin 的 Sequence 可以多平台使⽤
• Java 的 Stream 可以啟動 Parallel 模式,可以有很⼤幅度的
效能強化,但有些陷阱要注意
• 不使⽤ Parallel 模式時,很難說 Stream 的效能比
Sequence 好
主題 52
考慮使⽤ Map 來儲存關聯的元素
需要在 Collection 裡找東⻄的情境
—
• 從⼀個或多個檔案載入設定值的 Class
• 儲存下載資料的網路 Repository
• (在測試裡很常⽤的) 記憶體 Repository
從 Collection 裡取值時的考量
—
• 透過唯⼀值 (identifier、name、unique key) 在
Collection 裡搜尋取值
• 需要對每⼀個元素做比對
• 需考慮線性複雜度,愈⼤愈慢
Map 是個好解⽅
—
• Kotlin 的 Map 預設是⽤ LinkedHashMap 實作
• 從 HashMap 裡找東⻄快多了
• 但只有找東⻄快,假如是修改或是迭代元素的話,List 和
Map 的差異不⼤
⽤ List 實作
—
class InMemoryUserRepoWithList : UserRepo {
private val users: MutableList<User> = mutableListOf()
override fun getUser(id: Int): User? = users
.firstOrNull { it.id !" id }
fun addUser(user: User) {
users.add(user)
}
}
⽤ Map 實作
—
class InMemoryUserRepoWithMap : UserRepo {
private val users: MutableMap<Int, User> = mutableMapOf()
override fun getUser(id: Int): User? = users[id]
fun addUser(user: User) {
users[user.id] = user
}
}
轉換 List 成 Map
—
val users = listOf(
User(1, "Michal"),
User(2, "Mark"),
User(3, "Mark"),
)
val byId: Map<Int, User> = users.associateBy { it.id }
println(byId)
!" { 1=User(id=1, name=Michal),
!" 2=User(id=2, name=Mark),
!" 3=User(id=3, name=Mark) }
val byName: Map<String, User> = users.associateBy { it.name }
println(byName)
!" { Michal=User(id=1, name=Michal),
!" Mark=User(id=3, name=Mark) }
‼注意 Key 要唯⼀,不
然會被覆蓋
再從 Map 轉回 List
—
val originalList = byId.values
println(originalList)
!" [ User(id=1, name=Michal),
!" User(id=2, name=Mark),
!" User(id=3, name=Mark) ]
實務範例 pt.1
—
class ConfigurationsRepository(
configurations: List<Configuration>,
) {
private val configurations: Map<String, Configuration> =
configurations.associateBy { it.name }
fun getByName(name: String) = configurations[name]
}
實務範例 pt.2
—
class NetworkUserRepo(
private val userService: UserService,
) : UserRepo {
private var users: Map<Int, User>? = null
suspend fun loadUsers() {
users = userService.getUsers().associateBy { it.id }
}
override fun getUser(id: Int): User? = users!&get(id)
}
使⽤時機
—
• 很常需要從 Collection 裡找東⻄時
• ⼀般來說後端 (Server-Side) 比較常⽤,前端 (Mobile) 比較少⽤
主題 53
考慮使⽤ groupingBy 來取代 groupBy
模擬情境
—
• 在⼀個使⽤者清單裡,依照其所在城市來計算⼈數
• 在⼀個球員清單裡,依照其團隊來計算總分
• 在⼀個選項清單裡,依照其分類來找出最好選擇
情境實作
—
val usersCount: Map<City, Int> =
users.groupBy { it.city }
.mapValues { (_, users) !" users.size }
val pointsPerTeam: Map<Team, Int> =
players.groupBy { it.team }
.mapValues { (_, players) !"
players.sumOf { it.points }
}
val bestFormatPerQuality: Map<Quality, Resolution> =
formats.groupBy { it.quality }
.mapValues { (_, list) !"
list.maxOfOrNull { it.resolution }!'
}
groupBy 和 groupingBy
—
• 使⽤ groupBy()
- 中間多了幾層操作
- ⽅便、好懂
• 使⽤ groupingBy()
- 去掉中間的操作,但要搭配 eachCount()、fold()、
reduce()、aggregate() 使⽤
- 不好理解
圖解 groupingBy() + eachCount()
—
"
"
"
#
# ⭐ ⭐ ⭐
#
# ⭐
⭐ ⭐ " "
"
groupingBy()
eachCount()
= 2,
# ⭐ = 3, " = 3
情境實作 pt.1
—
val usersCount: Map<City, Int> =
users.groupingBy { it.city }
.eachCount()
情境實作 pt.2-1
—
val pointsPerTeam: Map<Team, Int> =
players.groupingBy { it.team }
.fold(0) { accumulator, player !"
accumulator + player.points
}
情境實作 pt.2-2
—
val pointsPerTeamWithExtension: Map<Team, Int> =
players.groupingBy { it.team }
.eachSumBy{ it.points }
!( Extension Function
fun <T, K> Grouping<T, K>.eachSumBy(
selector: (T) !) Int
): Map<K, Int> = this.fold(0) { accumulator, element !"
accumulator + selector(element)
}
主題 54
限制操作的數量
什麼時候會有效能考量?
—
• 使⽤ Collection 的時候
- 對元素有額外的迭代
- 在迭代時有額外的 Collection 被建立
• 使⽤ Sequence 的時候
- 有額外的物件包裏整個 Sequence 時
- 建立 Lambda 表達式時
總之就是
愈少操作愈好
— !" Works
fun List<User>.getNames(): List<String> =
this.map { it.name }
.filter { it !* null }
.map { it!' }
!" Better
fun List<User>.getNames(): List<String> =
this.map { it.name }
.filterNotNull()
!" Best
fun List<User>.getNames(): List<String> =
this.mapNotNull { it.name }
要怎麼才能辦到?
—
• 依賴 IDE 提⽰
• 把表格背起來
主題 55
(有效能考量時) 使⽤ Primitive Array 來操作資料
Primitive Type 的優勢
—
• 輕量 (多⼀層物件就多⼀層重量)
• 快 (透過 accessor 取值會有額外的成本)
Kotlin 的天性
—
• 在底層封裝了 Primitive Type (⾃動最佳化)
• Collection 裡放的是 Generic
• 但還是有⽅法可以⽤ Primitive Type…
對照表
—
差異比較 pt.1
—
val ints: List<Int> = List(1_000_000) { it }
val array: Array<Int> = ints.toTypedArray()
val intArray: IntArray = ints.toIntArray()
println(getObjectSize(ints)) !" 20 000 040
println(getObjectSize(array)) !" 20 000 016
println(getObjectSize(intArray)) !" 4 000 016
差異比較 pt.2
—
open class PrimitiveArrayBenchmark {
lateinit var list: List<Int>
lateinit var array: IntArray
@Setup
fun init() {
list = List(1_000_000) { it }
array = IntArray (1_000_000) { it }
}
@Benchmark
!" On average 1 260 593 ns
fun averageOnIntList(): Double {
return list.average()
}
@Benchmark
!" On average 868 509 ns
fun averageOnIntArray(): Double {
return array.average()
}
}
後話
—
• 對比於 List,使⽤ Primitive 在⼤多數的情境下並沒有⾜夠明顯
的效能優勢
• ⽽使⽤ List 是更為直覺、⽅便的選擇
• 總之,應優先使⽤ List,有效能考量時再改⽤ Primitive
主題 56
考慮使⽤ Mutable Collection
為什麼要⽤ Mutable Collection?
—
• 使⽤ Immutable 是為了安全,給我們更多控制
• 使⽤ Mutable 是為了效能
• 取個平衡:
- 只在 Local Processing 的時候⽤ Mutable Collection
- 像是在寫 Utils 的時候,常常修改 Collection 內容時
底層實作
—
public operator fun <T> Iterable<T>.plus(
elements: Array<out T>
): List<T> {
if (this is Collection) return this.plus(elements)
val result = ArrayList<T>()
result.addAll(this)
result.addAll(elements)
return result
}
Kotlin Collection
全⽅位解析攻略
—
collection.kotlin.tips
• 詳解 200+ Collection ⽅法
• 解析標準函式庫原始碼
• 實務範例
• 免費下載速查地圖
內容三⼤組成
—
技法 ⼼法 實戰
快速充實腦中的
Collection ⼯具箱
追溯 Collection 原始碼
了解其語法設計與應⽤
透過情境解題
將 Collection 應⽤於⽇常任務
拆分成九⼤分類
—
繪製成速查⼼智圖
—
與本章有關的章節
—
• 主題 51:傾向使⽤ Sequences 來取代 Collection
- 2-3-3 提升處理⼤量資料時的效能 (p.2-78)
- 4-4 關於效能與效率的反思 (p.4-6)
• 主題 52:考慮使⽤ Map 來儲存關聯的元素
- 1-9-6 Associate 系列⽅法 (p.1-164)
與本章有關的章節
—
• 主題 53:考慮使⽤ groupingBy 來取代 groupBy
- 1-10-5 With-grouping 系列⽅法 (p.1-199)
- 3-2 資料統計運算 (p.3-18)
• 主題 54:限制操作的數量
- 4-3 條條⼤路通羅⾺ (p.4-3)
與本章有關的章節
—
• 主題 55:(有效能考量時) 使⽤ Primitive Array 來操作資料
- 1-11-1 toArray 系列⽅法 (p.1-203)
• 主題 56:考慮使⽤ Mutable Collection
-
關注粉絲⾴及頻道
—
Coding 職⼈塾
Kraftsman

More Related Content

What's hot

Jetpack Compose.pptx
Jetpack Compose.pptxJetpack Compose.pptx
Jetpack Compose.pptxGDSCVJTI
 
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代[JCConf 2020] 用 Kotlin 跨入 Serverless 世代
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代Shengyou Fan
 
Android jetpack compose | Declarative UI
Android jetpack compose | Declarative UI Android jetpack compose | Declarative UI
Android jetpack compose | Declarative UI Ajinkya Saswade
 
Visual Studio を使わず .NET する
Visual Studio を使わず .NET するVisual Studio を使わず .NET する
Visual Studio を使わず .NET するm ishizaki
 
JDKの選択肢とサーバーサイドでの選び方
JDKの選択肢とサーバーサイドでの選び方JDKの選択肢とサーバーサイドでの選び方
JDKの選択肢とサーバーサイドでの選び方Takahiro YAMADA
 
進擊的前端工程師:今天就用 JSON Server 自己打造 API 吧!
進擊的前端工程師:今天就用 JSON Server 自己打造 API 吧!進擊的前端工程師:今天就用 JSON Server 自己打造 API 吧!
進擊的前端工程師:今天就用 JSON Server 自己打造 API 吧!Will Huang
 
老派浪漫:用 Kotlin 寫 Command Line 工具
老派浪漫:用 Kotlin 寫 Command Line 工具老派浪漫:用 Kotlin 寫 Command Line 工具
老派浪漫:用 Kotlin 寫 Command Line 工具Shengyou Fan
 
GraalVMで使われている、他言語をJVM上に実装する仕組みを学ぼう
GraalVMで使われている、他言語をJVM上に実装する仕組みを学ぼうGraalVMで使われている、他言語をJVM上に実装する仕組みを学ぼう
GraalVMで使われている、他言語をJVM上に実装する仕組みを学ぼうKoichi Sakata
 
[PHP 也有 Day #64] PHP 升級指南
[PHP 也有 Day #64] PHP 升級指南[PHP 也有 Day #64] PHP 升級指南
[PHP 也有 Day #64] PHP 升級指南Shengyou Fan
 
LLVM 總是打開你的心:從電玩模擬器看編譯器應用實例
LLVM 總是打開你的心:從電玩模擬器看編譯器應用實例LLVM 總是打開你的心:從電玩模擬器看編譯器應用實例
LLVM 總是打開你的心:從電玩模擬器看編譯器應用實例National Cheng Kung University
 
Azure Machine Learning 重頭學
Azure Machine Learning 重頭學Azure Machine Learning 重頭學
Azure Machine Learning 重頭學Ko Ko
 
GraalVMの紹介とTruffleでPHPぽい言語を実装したら爆速だった話
GraalVMの紹介とTruffleでPHPぽい言語を実装したら爆速だった話GraalVMの紹介とTruffleでPHPぽい言語を実装したら爆速だった話
GraalVMの紹介とTruffleでPHPぽい言語を実装したら爆速だった話なおき きしだ
 
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang) [Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang) Johnny Sung
 
仮想DOMを理解する
仮想DOMを理解する仮想DOMを理解する
仮想DOMを理解するK K
 
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로Jaeseung Ha
 

What's hot (20)

What Can Compilers Do for Us?
What Can Compilers Do for Us?What Can Compilers Do for Us?
What Can Compilers Do for Us?
 
Jetpack Compose.pptx
Jetpack Compose.pptxJetpack Compose.pptx
Jetpack Compose.pptx
 
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代[JCConf 2020] 用 Kotlin 跨入 Serverless 世代
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代
 
Android jetpack compose | Declarative UI
Android jetpack compose | Declarative UI Android jetpack compose | Declarative UI
Android jetpack compose | Declarative UI
 
Visual Studio を使わず .NET する
Visual Studio を使わず .NET するVisual Studio を使わず .NET する
Visual Studio を使わず .NET する
 
JDKの選択肢とサーバーサイドでの選び方
JDKの選択肢とサーバーサイドでの選び方JDKの選択肢とサーバーサイドでの選び方
JDKの選択肢とサーバーサイドでの選び方
 
進擊的前端工程師:今天就用 JSON Server 自己打造 API 吧!
進擊的前端工程師:今天就用 JSON Server 自己打造 API 吧!進擊的前端工程師:今天就用 JSON Server 自己打造 API 吧!
進擊的前端工程師:今天就用 JSON Server 自己打造 API 吧!
 
老派浪漫:用 Kotlin 寫 Command Line 工具
老派浪漫:用 Kotlin 寫 Command Line 工具老派浪漫:用 Kotlin 寫 Command Line 工具
老派浪漫:用 Kotlin 寫 Command Line 工具
 
GraalVMで使われている、他言語をJVM上に実装する仕組みを学ぼう
GraalVMで使われている、他言語をJVM上に実装する仕組みを学ぼうGraalVMで使われている、他言語をJVM上に実装する仕組みを学ぼう
GraalVMで使われている、他言語をJVM上に実装する仕組みを学ぼう
 
[PHP 也有 Day #64] PHP 升級指南
[PHP 也有 Day #64] PHP 升級指南[PHP 也有 Day #64] PHP 升級指南
[PHP 也有 Day #64] PHP 升級指南
 
LLVM 總是打開你的心:從電玩模擬器看編譯器應用實例
LLVM 總是打開你的心:從電玩模擬器看編譯器應用實例LLVM 總是打開你的心:從電玩模擬器看編譯器應用實例
LLVM 總是打開你的心:從電玩模擬器看編譯器應用實例
 
LLVM introduction
LLVM introductionLLVM introduction
LLVM introduction
 
Azure Machine Learning 重頭學
Azure Machine Learning 重頭學Azure Machine Learning 重頭學
Azure Machine Learning 重頭學
 
GraalVMの紹介とTruffleでPHPぽい言語を実装したら爆速だった話
GraalVMの紹介とTruffleでPHPぽい言語を実装したら爆速だった話GraalVMの紹介とTruffleでPHPぽい言語を実装したら爆速だった話
GraalVMの紹介とTruffleでPHPぽい言語を実装したら爆速だった話
 
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang) [Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
 
from Source to Binary: How GNU Toolchain Works
from Source to Binary: How GNU Toolchain Worksfrom Source to Binary: How GNU Toolchain Works
from Source to Binary: How GNU Toolchain Works
 
仮想DOMを理解する
仮想DOMを理解する仮想DOMを理解する
仮想DOMを理解する
 
TypeScript VS JavaScript.pptx
TypeScript VS JavaScript.pptxTypeScript VS JavaScript.pptx
TypeScript VS JavaScript.pptx
 
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
 
Jenkins 再入門
Jenkins 再入門Jenkins 再入門
Jenkins 再入門
 

Similar to [Effective Kotlin 讀書會] 第八章 Efficient collection processing 導讀

Java 開發者的函數式程式設計
Java 開發者的函數式程式設計Java 開發者的函數式程式設計
Java 開發者的函數式程式設計Justin Lin
 
Python入門:5大概念初心者必備
Python入門:5大概念初心者必備Python入門:5大概念初心者必備
Python入門:5大概念初心者必備Derek Lee
 
Python learn guide
Python learn guidePython learn guide
Python learn guiderobin yang
 
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫Justin Lin
 
JavaScript 快速複習 2017Q1
JavaScript 快速複習 2017Q1JavaScript 快速複習 2017Q1
JavaScript 快速複習 2017Q1Sheng-Han Su
 
Python入門:5大概念初心者必備 2021/11/18
Python入門:5大概念初心者必備 2021/11/18Python入門:5大概念初心者必備 2021/11/18
Python入門:5大概念初心者必備 2021/11/18Derek Lee
 
lambda/closure – JavaScript、Python、Scala 到 Java SE 7
lambda/closure – JavaScript、Python、Scala 到 Java SE 7lambda/closure – JavaScript、Python、Scala 到 Java SE 7
lambda/closure – JavaScript、Python、Scala 到 Java SE 7Justin Lin
 
CKAN : 資料開放平台技術介紹 (CAKN : Technical Introduction to Open Data Portal)
CKAN : 資料開放平台技術介紹 (CAKN : Technical Introduction to Open Data Portal)CKAN : 資料開放平台技術介紹 (CAKN : Technical Introduction to Open Data Portal)
CKAN : 資料開放平台技術介紹 (CAKN : Technical Introduction to Open Data Portal)Jian-Kai Wang
 
Free Marker中文文档
Free Marker中文文档Free Marker中文文档
Free Marker中文文档yiditushe
 
Python速成指南
Python速成指南Python速成指南
Python速成指南March Liu
 
Pytables
PytablesPytables
Pytablesgowell
 

Similar to [Effective Kotlin 讀書會] 第八章 Efficient collection processing 導讀 (20)

Java 開發者的函數式程式設計
Java 開發者的函數式程式設計Java 開發者的函數式程式設計
Java 開發者的函數式程式設計
 
Python入門:5大概念初心者必備
Python入門:5大概念初心者必備Python入門:5大概念初心者必備
Python入門:5大概念初心者必備
 
Python learn guide
Python learn guidePython learn guide
Python learn guide
 
Python 温故
Python 温故Python 温故
Python 温故
 
functional-scala
functional-scalafunctional-scala
functional-scala
 
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
 
JavaScript 快速複習 2017Q1
JavaScript 快速複習 2017Q1JavaScript 快速複習 2017Q1
JavaScript 快速複習 2017Q1
 
Scala+spark 2nd
Scala+spark 2ndScala+spark 2nd
Scala+spark 2nd
 
Python入門:5大概念初心者必備 2021/11/18
Python入門:5大概念初心者必備 2021/11/18Python入門:5大概念初心者必備 2021/11/18
Python入門:5大概念初心者必備 2021/11/18
 
Scala
ScalaScala
Scala
 
lambda/closure – JavaScript、Python、Scala 到 Java SE 7
lambda/closure – JavaScript、Python、Scala 到 Java SE 7lambda/closure – JavaScript、Python、Scala 到 Java SE 7
lambda/closure – JavaScript、Python、Scala 到 Java SE 7
 
Scala+RDD
Scala+RDDScala+RDD
Scala+RDD
 
Eloquent ORM
Eloquent ORMEloquent ORM
Eloquent ORM
 
CKAN : 資料開放平台技術介紹 (CAKN : Technical Introduction to Open Data Portal)
CKAN : 資料開放平台技術介紹 (CAKN : Technical Introduction to Open Data Portal)CKAN : 資料開放平台技術介紹 (CAKN : Technical Introduction to Open Data Portal)
CKAN : 資料開放平台技術介紹 (CAKN : Technical Introduction to Open Data Portal)
 
ios分享
ios分享ios分享
ios分享
 
Free Marker中文文档
Free Marker中文文档Free Marker中文文档
Free Marker中文文档
 
Python速成指南
Python速成指南Python速成指南
Python速成指南
 
Pytables
PytablesPytables
Pytables
 
I os 02
I os 02I os 02
I os 02
 
Eloquent ORM
Eloquent ORMEloquent ORM
Eloquent ORM
 

More from Shengyou Fan

[GDG Kaohsiung DevFest 2023] 以 Compose 及 Kotlin Multiplatform 打造多平台應用程式
[GDG Kaohsiung DevFest 2023] 以 Compose 及 Kotlin Multiplatform 打造多平台應用程式[GDG Kaohsiung DevFest 2023] 以 Compose 及 Kotlin Multiplatform 打造多平台應用程式
[GDG Kaohsiung DevFest 2023] 以 Compose 及 Kotlin Multiplatform 打造多平台應用程式Shengyou Fan
 
[JCConf 2023] 從 Kotlin Multiplatform 到 Compose Multiplatform:在多平台間輕鬆共用業務邏輯與 U...
[JCConf 2023] 從 Kotlin Multiplatform 到 Compose Multiplatform:在多平台間輕鬆共用業務邏輯與 U...[JCConf 2023] 從 Kotlin Multiplatform 到 Compose Multiplatform:在多平台間輕鬆共用業務邏輯與 U...
[JCConf 2023] 從 Kotlin Multiplatform 到 Compose Multiplatform:在多平台間輕鬆共用業務邏輯與 U...Shengyou Fan
 
[Kotlin 讀書會第五梯次] 深入淺出 Kotlin 第一章導讀
[Kotlin 讀書會第五梯次] 深入淺出 Kotlin 第一章導讀[Kotlin 讀書會第五梯次] 深入淺出 Kotlin 第一章導讀
[Kotlin 讀書會第五梯次] 深入淺出 Kotlin 第一章導讀Shengyou Fan
 
[WebConf Taiwan 2023] 一份 Zend Engine 外帶!透過 Micro 讓一次打包、多處運行變得可能
[WebConf Taiwan 2023] 一份 Zend Engine 外帶!透過 Micro 讓一次打包、多處運行變得可能[WebConf Taiwan 2023] 一份 Zend Engine 外帶!透過 Micro 讓一次打包、多處運行變得可能
[WebConf Taiwan 2023] 一份 Zend Engine 外帶!透過 Micro 讓一次打包、多處運行變得可能Shengyou Fan
 
How I make a podcast website using serverless technology in 2023
How I make a podcast website using serverless technology in 2023How I make a podcast website using serverless technology in 2023
How I make a podcast website using serverless technology in 2023Shengyou Fan
 
Using the Exposed SQL Framework to Manage Your Database
Using the Exposed SQL Framework to Manage Your DatabaseUsing the Exposed SQL Framework to Manage Your Database
Using the Exposed SQL Framework to Manage Your DatabaseShengyou Fan
 
[COSCUP 2022] 讓黑畫面再次偉大 - 用 PHP 寫 CLI 工具
[COSCUP 2022] 讓黑畫面再次偉大 - 用 PHP 寫 CLI 工具[COSCUP 2022] 讓黑畫面再次偉大 - 用 PHP 寫 CLI 工具
[COSCUP 2022] 讓黑畫面再次偉大 - 用 PHP 寫 CLI 工具Shengyou Fan
 
[COSCUP 2022] Kotlin Collection 遊樂園
[COSCUP 2022] Kotlin Collection 遊樂園[COSCUP 2022] Kotlin Collection 遊樂園
[COSCUP 2022] Kotlin Collection 遊樂園Shengyou Fan
 
簡化 JVM 上雲 - 透過 Azure Spring Cloud 提升開發、發佈及服務監控效率
簡化 JVM 上雲 - 透過 Azure Spring Cloud 提升開發、發佈及服務監控效率簡化 JVM 上雲 - 透過 Azure Spring Cloud 提升開發、發佈及服務監控效率
簡化 JVM 上雲 - 透過 Azure Spring Cloud 提升開發、發佈及服務監控效率Shengyou Fan
 
Composer 經典食譜
Composer 經典食譜Composer 經典食譜
Composer 經典食譜Shengyou Fan
 
[Kotlin Serverless 工作坊] 單元 4 - 實作 RSS Aggregator
[Kotlin Serverless 工作坊] 單元 4 - 實作 RSS Aggregator[Kotlin Serverless 工作坊] 單元 4 - 實作 RSS Aggregator
[Kotlin Serverless 工作坊] 單元 4 - 實作 RSS AggregatorShengyou Fan
 
[Kotlin Serverless 工作坊] 單元 3 - 實作 JSON API
[Kotlin Serverless 工作坊] 單元 3 - 實作 JSON API[Kotlin Serverless 工作坊] 單元 3 - 實作 JSON API
[Kotlin Serverless 工作坊] 單元 3 - 實作 JSON APIShengyou Fan
 
[Kotlin Serverless 工作坊] 單元 2 - 簡介 Kotlin Serverless
[Kotlin Serverless 工作坊] 單元 2 - 簡介 Kotlin Serverless[Kotlin Serverless 工作坊] 單元 2 - 簡介 Kotlin Serverless
[Kotlin Serverless 工作坊] 單元 2 - 簡介 Kotlin ServerlessShengyou Fan
 
[Kotlin Serverless 工作坊] 單元 1 - 開發環境建置
[Kotlin Serverless 工作坊] 單元 1 - 開發環境建置[Kotlin Serverless 工作坊] 單元 1 - 開發環境建置
[Kotlin Serverless 工作坊] 單元 1 - 開發環境建置Shengyou Fan
 
用 Kotlin 打造讀書會小幫手
用 Kotlin 打造讀書會小幫手用 Kotlin 打造讀書會小幫手
用 Kotlin 打造讀書會小幫手Shengyou Fan
 
Kotlin 讀書會第三梯次第一章
Kotlin 讀書會第三梯次第一章Kotlin 讀書會第三梯次第一章
Kotlin 讀書會第三梯次第一章Shengyou Fan
 
用 OPENRNDR 將 Chatbot 訊息視覺化
用 OPENRNDR 將 Chatbot 訊息視覺化用 OPENRNDR 將 Chatbot 訊息視覺化
用 OPENRNDR 將 Chatbot 訊息視覺化Shengyou Fan
 
[PHP 也有 Day] 垃圾留言守城記 - 用 Laravel 阻擋 SPAM 留言的奮鬥史
[PHP 也有 Day] 垃圾留言守城記 - 用 Laravel 阻擋 SPAM 留言的奮鬥史[PHP 也有 Day] 垃圾留言守城記 - 用 Laravel 阻擋 SPAM 留言的奮鬥史
[PHP 也有 Day] 垃圾留言守城記 - 用 Laravel 阻擋 SPAM 留言的奮鬥史Shengyou Fan
 
Ktor 部署攻略 - 老派 Fat Jar 大法
Ktor 部署攻略 - 老派 Fat Jar 大法Ktor 部署攻略 - 老派 Fat Jar 大法
Ktor 部署攻略 - 老派 Fat Jar 大法Shengyou Fan
 
以 Kotlin 快速打造 Mobile Backend
以 Kotlin 快速打造 Mobile Backend以 Kotlin 快速打造 Mobile Backend
以 Kotlin 快速打造 Mobile BackendShengyou Fan
 

More from Shengyou Fan (20)

[GDG Kaohsiung DevFest 2023] 以 Compose 及 Kotlin Multiplatform 打造多平台應用程式
[GDG Kaohsiung DevFest 2023] 以 Compose 及 Kotlin Multiplatform 打造多平台應用程式[GDG Kaohsiung DevFest 2023] 以 Compose 及 Kotlin Multiplatform 打造多平台應用程式
[GDG Kaohsiung DevFest 2023] 以 Compose 及 Kotlin Multiplatform 打造多平台應用程式
 
[JCConf 2023] 從 Kotlin Multiplatform 到 Compose Multiplatform:在多平台間輕鬆共用業務邏輯與 U...
[JCConf 2023] 從 Kotlin Multiplatform 到 Compose Multiplatform:在多平台間輕鬆共用業務邏輯與 U...[JCConf 2023] 從 Kotlin Multiplatform 到 Compose Multiplatform:在多平台間輕鬆共用業務邏輯與 U...
[JCConf 2023] 從 Kotlin Multiplatform 到 Compose Multiplatform:在多平台間輕鬆共用業務邏輯與 U...
 
[Kotlin 讀書會第五梯次] 深入淺出 Kotlin 第一章導讀
[Kotlin 讀書會第五梯次] 深入淺出 Kotlin 第一章導讀[Kotlin 讀書會第五梯次] 深入淺出 Kotlin 第一章導讀
[Kotlin 讀書會第五梯次] 深入淺出 Kotlin 第一章導讀
 
[WebConf Taiwan 2023] 一份 Zend Engine 外帶!透過 Micro 讓一次打包、多處運行變得可能
[WebConf Taiwan 2023] 一份 Zend Engine 外帶!透過 Micro 讓一次打包、多處運行變得可能[WebConf Taiwan 2023] 一份 Zend Engine 外帶!透過 Micro 讓一次打包、多處運行變得可能
[WebConf Taiwan 2023] 一份 Zend Engine 外帶!透過 Micro 讓一次打包、多處運行變得可能
 
How I make a podcast website using serverless technology in 2023
How I make a podcast website using serverless technology in 2023How I make a podcast website using serverless technology in 2023
How I make a podcast website using serverless technology in 2023
 
Using the Exposed SQL Framework to Manage Your Database
Using the Exposed SQL Framework to Manage Your DatabaseUsing the Exposed SQL Framework to Manage Your Database
Using the Exposed SQL Framework to Manage Your Database
 
[COSCUP 2022] 讓黑畫面再次偉大 - 用 PHP 寫 CLI 工具
[COSCUP 2022] 讓黑畫面再次偉大 - 用 PHP 寫 CLI 工具[COSCUP 2022] 讓黑畫面再次偉大 - 用 PHP 寫 CLI 工具
[COSCUP 2022] 讓黑畫面再次偉大 - 用 PHP 寫 CLI 工具
 
[COSCUP 2022] Kotlin Collection 遊樂園
[COSCUP 2022] Kotlin Collection 遊樂園[COSCUP 2022] Kotlin Collection 遊樂園
[COSCUP 2022] Kotlin Collection 遊樂園
 
簡化 JVM 上雲 - 透過 Azure Spring Cloud 提升開發、發佈及服務監控效率
簡化 JVM 上雲 - 透過 Azure Spring Cloud 提升開發、發佈及服務監控效率簡化 JVM 上雲 - 透過 Azure Spring Cloud 提升開發、發佈及服務監控效率
簡化 JVM 上雲 - 透過 Azure Spring Cloud 提升開發、發佈及服務監控效率
 
Composer 經典食譜
Composer 經典食譜Composer 經典食譜
Composer 經典食譜
 
[Kotlin Serverless 工作坊] 單元 4 - 實作 RSS Aggregator
[Kotlin Serverless 工作坊] 單元 4 - 實作 RSS Aggregator[Kotlin Serverless 工作坊] 單元 4 - 實作 RSS Aggregator
[Kotlin Serverless 工作坊] 單元 4 - 實作 RSS Aggregator
 
[Kotlin Serverless 工作坊] 單元 3 - 實作 JSON API
[Kotlin Serverless 工作坊] 單元 3 - 實作 JSON API[Kotlin Serverless 工作坊] 單元 3 - 實作 JSON API
[Kotlin Serverless 工作坊] 單元 3 - 實作 JSON API
 
[Kotlin Serverless 工作坊] 單元 2 - 簡介 Kotlin Serverless
[Kotlin Serverless 工作坊] 單元 2 - 簡介 Kotlin Serverless[Kotlin Serverless 工作坊] 單元 2 - 簡介 Kotlin Serverless
[Kotlin Serverless 工作坊] 單元 2 - 簡介 Kotlin Serverless
 
[Kotlin Serverless 工作坊] 單元 1 - 開發環境建置
[Kotlin Serverless 工作坊] 單元 1 - 開發環境建置[Kotlin Serverless 工作坊] 單元 1 - 開發環境建置
[Kotlin Serverless 工作坊] 單元 1 - 開發環境建置
 
用 Kotlin 打造讀書會小幫手
用 Kotlin 打造讀書會小幫手用 Kotlin 打造讀書會小幫手
用 Kotlin 打造讀書會小幫手
 
Kotlin 讀書會第三梯次第一章
Kotlin 讀書會第三梯次第一章Kotlin 讀書會第三梯次第一章
Kotlin 讀書會第三梯次第一章
 
用 OPENRNDR 將 Chatbot 訊息視覺化
用 OPENRNDR 將 Chatbot 訊息視覺化用 OPENRNDR 將 Chatbot 訊息視覺化
用 OPENRNDR 將 Chatbot 訊息視覺化
 
[PHP 也有 Day] 垃圾留言守城記 - 用 Laravel 阻擋 SPAM 留言的奮鬥史
[PHP 也有 Day] 垃圾留言守城記 - 用 Laravel 阻擋 SPAM 留言的奮鬥史[PHP 也有 Day] 垃圾留言守城記 - 用 Laravel 阻擋 SPAM 留言的奮鬥史
[PHP 也有 Day] 垃圾留言守城記 - 用 Laravel 阻擋 SPAM 留言的奮鬥史
 
Ktor 部署攻略 - 老派 Fat Jar 大法
Ktor 部署攻略 - 老派 Fat Jar 大法Ktor 部署攻略 - 老派 Fat Jar 大法
Ktor 部署攻略 - 老派 Fat Jar 大法
 
以 Kotlin 快速打造 Mobile Backend
以 Kotlin 快速打造 Mobile Backend以 Kotlin 快速打造 Mobile Backend
以 Kotlin 快速打造 Mobile Backend
 

[Effective Kotlin 讀書會] 第八章 Efficient collection processing 導讀