Lambda Expressions trong Kotlin
🎯 Mục tiêu: Hiểu và sử dụng lambda - nền tảng của functional programming trong Kotlin.
💡 Khái niệm
Lambda là hàm ẩn danh (anonymous function) có thể được lưu trong biến và truyền như tham số.
// Lambda cơ bản
val greet = { println("Hello!") }
greet() // Hello!
// Lambda với tham số
val sum = { a: Int, b: Int -> a + b }
println(sum(5, 3)) // 8📝 Cú pháp Lambda
Full syntax
val lambda: (Int, Int) -> Int = { a: Int, b: Int -> a + b }Type inference
// Compiler tự suy luận kiểu
val sum = { a: Int, b: Int -> a + b }
// Hoặc khai báo kiểu bên ngoài
val sum: (Int, Int) -> Int = { a, b -> a + b }Single parameter: it
val double: (Int) -> Int = { it * 2 }
println(double(5)) // 10
val isEven: (Int) -> Boolean = { it % 2 == 0 }
println(isEven(4)) // true🔗 Lambda với Collections
map - Biến đổi từng phần tử
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", "charlie")
val capitalized = names.map { it.uppercase() }
println(capitalized) // [ALICE, BOB, CHARLIE]filter - Lọc phần tử
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val evenNumbers = numbers.filter { it % 2 == 0 }
println(evenNumbers) // [2, 4, 6, 8, 10]
val longNames = names.filter { it.length > 3 }
println(longNames) // [alice, charlie]reduce/fold - Gộp thành một giá trị
val numbers = listOf(1, 2, 3, 4, 5)
val sum = numbers.reduce { acc, n -> acc + n }
println(sum) // 15
val product = numbers.fold(1) { acc, n -> acc * n }
println(product) // 120🎯 Trailing Lambda Syntax
Khi lambda là tham số cuối cùng, có thể đặt ngoài dấu ngoặc:
// Bình thường
numbers.filter({ it > 3 })
// Trailing lambda (khuyến nghị)
numbers.filter { it > 3 }
// Nhiều lambdas
listOf(1, 2, 3).fold(0, { acc, n -> acc + n })
listOf(1, 2, 3).fold(0) { acc, n -> acc + n }📦 Lambda với nhiều statements
val process = { name: String ->
println("Processing $name...")
val result = name.uppercase()
println("Done!")
result // Giá trị cuối cùng được return
}
val output = process("kotlin") // "KOTLIN"🔄 Lambda vs Anonymous Function
// Lambda - implicit return
val sum1 = { a: Int, b: Int -> a + b }
// Anonymous function - explicit return
val sum2 = fun(a: Int, b: Int): Int {
return a + b
}
// Anonymous function một dòng
val sum3 = fun(a: Int, b: Int) = a + bKhác biệt với return
fun example() {
val numbers = listOf(1, 2, 3)
// Lambda - return thoát function bên ngoài
numbers.forEach {
if (it == 2) return // Thoát example()
println(it)
}
println("Done") // Không chạy nếu có 2
}
fun exampleWithLabel() {
val numbers = listOf(1, 2, 3)
// Lambda với label - return thoát lambda
numbers.forEach {
if (it == 2) return@forEach
println(it)
}
println("Done") // Vẫn chạy
}🛠️ Thực hành
Bài tập 1: Chuyển đổi data
fun main() {
val users = listOf(
mapOf("name" to "Alice", "age" to 25),
mapOf("name" to "Bob", "age" to 30),
mapOf("name" to "Charlie", "age" to 20)
)
// TODO: Lấy danh sách tên của những người >= 25 tuổi
}Lời giải:
fun main() {
val users = listOf(
mapOf("name" to "Alice", "age" to 25),
mapOf("name" to "Bob", "age" to 30),
mapOf("name" to "Charlie", "age" to 20)
)
val names = users
.filter { (it["age"] as Int) >= 25 }
.map { it["name"] as String }
println(names) // [Alice, Bob]
}Bài tập 2: Custom sort
fun main() {
val words = listOf("banana", "apple", "cherry", "date")
// TODO: Sắp xếp theo độ dài, sau đó theo alphabet
}Lời giải:
fun main() {
val words = listOf("banana", "apple", "cherry", "date")
val sorted = words.sortedWith(
compareBy({ it.length }, { it })
)
println(sorted) // [date, apple, banana, cherry]
}Bài tập 3: Tạo calculator với lambdas
fun main() {
// TODO: Tạo map chứa các operations
}Lời giải:
fun main() {
val operations: Map<String, (Double, Double) -> Double> = mapOf(
"+" to { a, b -> a + b },
"-" to { a, b -> a - b },
"*" to { a, b -> a * b },
"/" to { a, b -> if (b != 0.0) a / b else Double.NaN }
)
val a = 10.0
val b = 3.0
operations.forEach { (op, fn) ->
println("$a $op $b = ${fn(a, b)}")
}
}📱 Trong Android
// Click listeners
button.setOnClickListener {
println("Clicked!")
}
// RecyclerView adapter
items.forEach { item ->
holder.textView.text = item.name
}
// Retrofit callback
api.getUsers().enqueue(object : Callback<List<User>> {
override fun onResponse(call: Call<List<User>>, response: Response<List<User>>) {
response.body()?.let { users ->
users.filter { it.isActive }
.sortedBy { it.name }
.forEach { displayUser(it) }
}
}
})⚠️ Lưu ý quan trọng
[!TIP] Dùng
itkhi lambda có 1 tham số:// ✅ Clean numbers.filter { it > 0 } // ❌ Verbose numbers.filter { number -> number > 0 }
[!WARNING] Cẩn thận với
returntrong lambda:fun process() { listOf(1, 2, 3).forEach { if (it == 2) return // Thoát process(), không phải forEach! } }
✅ Checklist - Tự kiểm tra
Sau bài học này, bạn có thể:
- Định nghĩa lambda với cú pháp
{ params -> body } - Sử dụng
itcho lambda một tham số - Sử dụng trailing lambda syntax
- Áp dụng lambda với
map,filter,reduce - Hiểu khác biệt giữa lambda và anonymous function
Tiếp theo: Higher-Order Functions
Last updated on