Kotlin lambda 表达式
最后修改于 2024 年 1 月 29 日
在本文中,我们将展示如何在 Kotlin 中使用 lambda 表达式。
一个 lambda 表达式 是一个匿名函数,它被视为一个值。 它可以绑定到一个变量,作为参数传递给一个函数,或者从一个函数返回。
val square: (Int) -> Int = { e: Int -> e * e }
在 Kotlin 中,lambda 表达式总是用大括号分隔。
Kotlin 匿名函数
匿名函数是没有名称的函数。
package com.zetcode
fun main() {
val vals = intArrayOf(-2, -1, 0, 1, 2, 3, 4)
val filtered = vals.filter(fun(e) = e > 0)
println(filtered)
}
我们定义一个整数数组。 该数组使用 filter 函数进行过滤。 filter 函数将一个匿名函数作为参数。
val filtered = vals.filter(fun(e) = e > 0)
匿名函数用于过滤数组。
下一个示例使用 lambda 表达式重写了上一个示例。
package com.zetcode
fun main() {
val vals = intArrayOf(-2, -1, 0, 1, 2, 3, 4)
val filtered = vals.filter { e -> e > 0 }
println(filtered)
}
在这里,我们使用大括号和 -> 运算符。
类型声明
在 lambda 表达式类型声明中,我们有一个方括号中的参数列表,后跟箭头 -> 运算符,然后是返回类型。
package com.zetcode
fun main() {
val square: (Int) -> Int = { e: Int -> e * e }
val r1 = square(5)
val r2 = square(3)
println(r1)
println(r2)
}
在程序中,我们将一个 lambda 表达式绑定到一个值; 提供了完整的类型声明。
val square: (Int) -> Int = { e: Int -> e * e }
square 值绑定到一个 lambda 表达式,该表达式接受一个整数并返回一个整数。
类型推断
Kotlin 可以推断值的 数据类型,因此,我们可以省略一些声明。
package com.zetcode
fun main() {
val square1: (Int) -> Int = { e: Int -> e * e }
val square2 = { e: Int -> e * e }
val square3: (Int) -> Int = { e -> e * e }
// val square4 = { e -> e * e }
val r1 = square1(5)
val r2 = square2(3)
val r3 = square3(6)
println(r1)
println(r2)
println(r3)
}
在示例中,我们多次定义 square 函数。
val square1: (Int) -> Int = { e: Int -> e * e }
这是完整的类型声明。
val square2 = { e: Int -> e * e }
在这里,我们省略了 square2 名称的 lambda 声明。
val square3: (Int) -> Int = { e -> e * e }
在这种情况下,我们省略了 lambda 表达式中元素的声明。
// val square4 = { e -> e * e }
但是,我们不能省略这两个声明。 此代码无法编译。
Unit 类型用于不返回值 的表达式。
package com.zetcode
fun main() {
val l1 = { println("Hello there!") }
val l2: (String) -> Unit = { name: String ->
println("Hello $name!")
}
l1()
l2("Lucia")
}
如果我们在控制台中打印某些内容,我们不会返回任何内容。 对于这种情况,我们指定 Unit。
Kotlin lambda 表达式 it
it 是一个特殊的关键字,表示传递给 lambda 表达式的单个参数。
package com.zetcode
fun main() {
val nums = listOf(1, 2, 3, 4, 5, 6)
nums.forEach { println(it * 2) }
}
我们有一个整数列表。 使用 forEach,我们遍历元素列表并将它们乘以 2。
nums.forEach { println(it * 2) }
it 表示当前处理的项目。
将 lambdas 作为函数参数传递
在下面的示例中,我们将 lambda 表达式作为函数参数传递。
package com.zetcode
val inc = { e: Int -> e + 1 }
val dec = { e: Int -> e - 1 }
val square = { e: Int -> e * e }
val triple = { e: Int -> e * e * e }
fun doProcess(vals: List<Int>, f: (Int) -> Int) {
val processed = vals.map { e -> f(e) }
println(processed)
}
fun main() {
val vals = listOf(1, 2, 3, 4, 5, 6)
doProcess(vals, inc)
doProcess(vals, dec)
doProcess(vals, square)
doProcess(vals, triple)
}
我们定义了四个 lambdas:inc、dec、square、triple。 我们将 lambdas 传递给 doProcess 函数。
fun doProcess(vals: List<Int>, f: (Int) -> Int) {
val processed = vals.map { e -> f(e) }
println(processed)
}
我们为第二个参数提供类型声明:(Int) -> Int。 每个 lambda 接受一个整数并返回一个整数。
val processed = vals.map { e -> f(e) }
使用 map,我们在列表的每个元素上应用 lambda 表达式。
从 lambda 返回
lambda 中的最后一个表达式被返回。
package com.zetcode
val check = { u:Pair<String, Int> ->
when (u.second) {
in 0..75 -> "failed"
else -> "passed"
}
}
fun main() {
val students = listOf(
Pair("Maria", 98),
Pair("Pablo", 81),
Pair("Lucia", 45),
Pair("Peter", 98),
Pair("Simon", 73),
)
students.forEach {
val res = check(it)
println("${it.first} has $res")
}
}
在示例中,我们有一个学生列表。 我们检查哪些学生通过了考试。
val check = { u:Pair<String, Int> ->
when (u.second) {
in 0..75 -> "failed"
else -> "passed"
}
}
lambda 包含一个 when 表达式。 匹配的 arm 的值从 lambda 返回。
val res = check(it)
println("${it.first} has $res")
返回的值用于显示消息。
尾随 lambdas
如果函数的最后一个参数是一个函数,则 lambda 表达式可以放在括号之外。 如果 lambda 是唯一的参数,则可以完全省略括号。
package com.zetcode
data class User(val fname: String, val lname: String, val salary: Int)
fun main() {
val users = listOf(
User("John", "Doe", 1230),
User("Lucy", "Novak", 670),
User("Ben", "Walter", 2050),
User("Robin", "Brown", 2300),
User("Amy", "Doe", 1250),
User("Joe", "Draker", 1190),
User("Janet", "Doe", 980),
User("Albert", "Novak", 1930)
)
val r1 = users.maxBy({ u: User -> u.salary })
println(r1)
val r2 = users.maxBy() { u: User -> u.salary }
println(r2)
val r3 = users.maxBy { u: User -> u.salary }
println(r3)
}
在示例中,我们找到所有用户的最高工资。
val r1 = users.maxBy({ u: User -> u.salary })
println(r1)
在第一种情况下,我们将 lambda 表达式作为参数传递给 maxBy 函数。
val r2 = users.maxBy() { u: User -> u.salary }
println(r2)
由于 lambda 是最后一个参数,我们可以将其从括号中取出。
val r3 = users.maxBy { u: User -> u.salary }
println(r3)
由于 lambda 是唯一的参数,我们可以省略括号。
Kotlin 链接带有 lambdas 的函数
我们可以使用 lambda 表达式链接函数调用,创建简洁的代码。
package com.zetcode
fun main() {
val words = listOf("sky", "cup", "water", "den",
"knife", "earth", "falcon")
val res = words.filter { it.length == 5 }.sortedBy { it }
.map { it.replaceFirstChar(Char::titlecase) }
println(res)
}
我们过滤一个单词列表,对其进行排序,并将其元素大写。 所有这些都在一系列三个函数调用中完成。 这些函数具有尾随的 lambdas。
在 lambdas 中解构
参数可以在 lambda 表达式中解构。 对于未使用的变量,我们可以使用下划线 _ 字符。
package com.zetcode
fun main() {
val words = mapOf(
1 to "sky", 2 to "cup", 3 to "water", 4 to "den",
5 to "knife", 6 to "earth", 7 to "falcon"
)
words.forEach { (_, v) -> println(v) }
}
我们有一个单词映射。 我们使用 forEach 遍历该映射。 该映射的每个元素都被解构为一个键/值对。 由于我们不使用键,因此我们使用下划线字符。
来源
在本文中,我们介绍了 Kotlin lambda 表达式。
作者
列出 所有 Kotlin 教程。