λ Lambda Expressions
🎯 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
Phần tiêu đề “💡 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ảnval 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
Phần tiêu đề “📝 Cú pháp Lambda”Full syntax
Phần tiêu đề “Full syntax”val lambda: (Int, Int) -> Int = { a: Int, b: Int -> a + b }Type inference
Phần tiêu đề “Type inference”// Compiler tự suy luận kiểuval sum = { a: Int, b: Int -> a + b }
// Hoặc khai báo kiểu bên ngoàival sum: (Int, Int) -> Int = { a, b -> a + b }Single parameter: it
Phần tiêu đề “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
Phần tiêu đề “🔗 Lambda với Collections”map - Biến đổi từng phần tử
Phần tiêu đề “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ử
Phần tiêu đề “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ị
Phần tiêu đề “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
Phần tiêu đề “🎯 Trailing Lambda Syntax”Khi lambda là tham số cuối cùng, có thể đặt ngoài dấu ngoặc:
// Bình thườngnumbers.filter({ it > 3 })
// Trailing lambda (khuyến nghị)numbers.filter { it > 3 }
// Nhiều lambdaslistOf(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
Phần tiêu đề “📦 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
Phần tiêu đề “🔄 Lambda vs Anonymous Function”// Lambda - implicit returnval sum1 = { a: Int, b: Int -> a + b }
// Anonymous function - explicit returnval sum2 = fun(a: Int, b: Int): Int { return a + b}
// Anonymous function một dòngval sum3 = fun(a: Int, b: Int) = a + bKhác biệt với return
Phần tiêu đề “Khá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
Phần tiêu đề “🛠️ 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
Phần tiêu đề “📱 Trong Android”// Click listenersbutton.setOnClickListener { println("Clicked!")}
// RecyclerView adapteritems.forEach { item -> holder.textView.text = item.name}
// Retrofit callbackapi.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
Phần tiêu đề “⚠️ Lưu ý quan trọng”✅ Checklist - Tự kiểm tra
Phần tiêu đề “✅ 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