Lambda 與高階函數#
Lambda 是一種匿名函數,可以像值一樣被傳遞;高階函數(Higher-Order Function) 是接受函數作為參數、或回傳函數的函數。兩者是 Kotlin 函數式程式設計風格的核心。
1. Lambda 基本語法#
1
| val 變數名稱: (參數型別) -> 回傳型別 = { 參數 -> 函數體 }
|
1
2
3
4
| fun main() {
val greet: (String) -> String = { name -> "Hello, $name!" }
println(greet("Alice")) // 輸出:Hello, Alice!
}
|
it:單一參數的簡寫#
當 Lambda 只有一個參數時,可以省略參數宣告,直接使用 it 代替。
1
2
3
4
| fun main() {
val double: (Int) -> Int = { it * 2 }
println(double(5)) // 輸出:10
}
|
2. 高階函數#
函數作為參數#
1
2
3
4
5
6
7
8
9
10
11
| fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}
fun main() {
val sum = calculate(3, 4) { x, y -> x + y }
val product = calculate(3, 4) { x, y -> x * y }
println("加法:$sum") // 輸出:加法:7
println("乘法:$product") // 輸出:乘法:12
}
|
函數作為回傳值#
1
2
3
4
5
6
7
8
9
| fun makeMultiplier(factor: Int): (Int) -> Int {
return { number -> number * factor }
}
fun main() {
val triple = makeMultiplier(3)
println(triple(5)) // 輸出:15
println(triple(10)) // 輸出:30
}
|
3. 集合的高階函數#
這是 Lambda 最常見的應用場景。
map:轉換每個元素#
1
2
3
4
5
6
7
8
9
| fun main() {
val numbers = listOf(1, 2, 3, 4, 5)
val doubled = numbers.map { it * 2 }
println(doubled) // 輸出:[2, 4, 6, 8, 10]
val names = listOf("alice", "bob", "carol")
val upper = names.map { it.uppercase() }
println(upper) // 輸出:[ALICE, BOB, CAROL]
}
|
filter:篩選符合條件的元素#
1
2
3
4
5
6
7
8
9
| fun main() {
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8)
val evens = numbers.filter { it % 2 == 0 }
println(evens) // 輸出:[2, 4, 6, 8]
val words = listOf("apple", "banana", "avocado", "cherry")
val aWords = words.filter { it.startsWith("a") }
println(aWords) // 輸出:[apple, avocado]
}
|
reduce:將集合歸納為單一值#
1
2
3
4
5
| fun main() {
val numbers = listOf(1, 2, 3, 4, 5)
val sum = numbers.reduce { acc, n -> acc + n }
println(sum) // 輸出:15
}
|
fold:與 reduce 類似,但可指定初始值#
1
2
3
4
5
| fun main() {
val numbers = listOf(1, 2, 3, 4, 5)
val sumFrom100 = numbers.fold(100) { acc, n -> acc + n }
println(sumFrom100) // 輸出:115
}
|
forEach:遍歷每個元素#
1
2
3
4
5
6
7
8
| fun main() {
val fruits = listOf("Apple", "Banana", "Cherry")
fruits.forEach { println(it) }
// 輸出:
// Apple
// Banana
// Cherry
}
|
any / all / none:條件判斷#
1
2
3
4
5
6
7
| fun main() {
val numbers = listOf(1, 2, 3, 4, 5)
println(numbers.any { it > 4 }) // 輸出:true(有任何元素 > 4)
println(numbers.all { it > 0 }) // 輸出:true(所有元素 > 0)
println(numbers.none { it > 10 }) // 輸出:true(沒有元素 > 10)
}
|
鏈式呼叫#
多個高階函數可以串接,形成流暢的資料處理管線。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| data class Product(val name: String, val price: Int, val inStock: Boolean)
fun main() {
val products = listOf(
Product("筆記型電腦", 35000, true),
Product("滑鼠", 800, true),
Product("鍵盤", 1500, false),
Product("螢幕", 12000, true)
)
val result = products
.filter { it.inStock } // 只取有庫存的
.filter { it.price < 20000 } // 價格低於 20000
.map { it.name } // 只取名稱
.sorted() // 排序
println(result) // 輸出:[滑鼠, 螢幕]
}
|
4. 尾隨 Lambda(Trailing Lambda)#
當函數的最後一個參數是 Lambda 時,可以將 Lambda 移到括號外面,讓程式碼更易讀。
1
2
3
4
5
| // 一般寫法
numbers.filter({ it > 3 })
// 尾隨 Lambda 寫法
numbers.filter { it > 3 }
|
5. with 與 apply:作用域函數#
Kotlin 提供了幾個以 Lambda 為基礎的作用域函數(Scope Functions),讓物件操作更簡潔。
with:對物件執行多個操作,回傳 Lambda 結果#
1
2
3
4
5
6
7
8
9
| data class Person(var name: String, var age: Int)
fun main() {
val person = Person("Alice", 30)
val info = with(person) {
"姓名:$name,年齡:$age"
}
println(info) // 輸出:姓名:Alice,年齡:30
}
|
apply:對物件進行設定,回傳物件本身#
1
2
3
4
5
6
7
8
9
| data class Person(var name: String = "", var age: Int = 0)
fun main() {
val person = Person().apply {
name = "Bob"
age = 25
}
println(person) // 輸出:Person(name=Bob, age=25)
}
|
Reference#
https://kotlinlang.org/docs/lambdas.html