Kotlin 函数与 Lambda 表达式
1. 函数(Functions)
函数定义
kotlin
// 1. 基本函数
fun greet(name: String): String {
return "Hello, $name!"
}
// 2. 表达式函数体(单表达式函数)
fun add(a: Int, b: Int): Int = a + b
// 3. 类型推断
fun multiply(a: Int, b: Int) = a * b
// 4. 无返回值(Unit 可省略)
fun printMessage(msg: String): Unit {
println(msg)
}
// 等价于
fun printMessage(msg: String) {
println(msg)
}
函数参数
kotlin
// 1. 默认参数
fun createUser(name: String, age: Int = 18, city: String = "Beijing") {
println("Name: $name, Age: $age, City: $city")
}
// 2. 命名参数
createUser(name = "Alice", city = "Shanghai") // age 使用默认值 18
// 3. 可变参数
fun sum(vararg numbers: Int): Int {
return numbers.sum()
}
sum(1, 2, 3, 4, 5)
// 4. 函数参数
fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}
特殊函数
kotlin
// 1. 扩展函数
fun String.addExclamation(): String = "$this!"
val message = "Hello".addExclamation() // "Hello!"
// 2. 中缀函数
infix fun Int.times(str: String) = str.repeat(this)
val result = 3 times "Hi" // "HiHiHi"
// 3. 内联函数(用于高阶函数优化)
inline fun measureTime(block: () -> Unit) {
val start = System.currentTimeMillis()
block()
val end = System.currentTimeMillis()
println("Time: ${end - start}ms")
}
// 4. 尾递归函数
tailrec fun factorial(n: Int, accumulator: Int = 1): Int {
return if (n <= 1) accumulator else factorial(n - 1, n * accumulator)
}
// 5. 局部函数
fun outerFunction(x: Int) {
fun innerFunction(y: Int): Int {
return x + y // 可以访问外部函数的参数
}
println(innerFunction(5))
}
2. Lambda 表达式
基本语法
kotlin
// 1. 基本形式
val sum: (Int, Int) -> Int = { a, b -> a + b }
// 2. 类型推断
val multiply = { a: Int, b: Int -> a * b }
// 3. 单参数 lambda(可用 it)
val double: (Int) -> Int = { it * 2 }
val isEven: (Int) -> Boolean = { it % 2 == 0 }
// 4. 无参数 lambda
val sayHello: () -> Unit = { println("Hello!") }
// 5. 作为函数参数
listOf(1, 2, 3).forEach { println(it) }
// 6. 带接收者的 lambda(常用于 DSL)
val stringBuilder = StringBuilder().apply {
append("Hello")
append(" ")
append("World")
}
Lambda 与集合操作
kotlin
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 1. filter - 过滤
val evens = numbers.filter { it % 2 == 0 } // [2, 4, 6, 8, 10]
// 2. map - 转换
val squares = numbers.map { it * it } // [1, 4, 9, 16, 25, ...]
// 3. reduce - 累积操作
val sum = numbers.reduce { acc, num -> acc + num } // 55
// 4. fold - 带初始值的累积
val product = numbers.fold(1) { acc, num -> acc * num }
// 5. takeWhile/dropWhile - 条件截取
val lessThan5 = numbers.takeWhile { it < 5 } // [1, 2, 3, 4]
val from5 = numbers.dropWhile { it < 5 } // [5, 6, 7, 8, 9, 10]
// 6. sortedBy - 排序
val strings = listOf("apple", "banana", "cherry")
val sortedByLength = strings.sortedBy { it.length } // ["apple", "cherry", "banana"]
// 7. groupBy - 分组
val groupedByParity = numbers.groupBy {
if (it % 2 == 0) "even" else "odd"
}
// 结果: {"odd"=[1,3,5,7,9], "even"=[2,4,6,8,10]}
// 8. flatMap - 扁平化映射
val nested = listOf(listOf(1, 2), listOf(3, 4), listOf(5, 6))
val flat = nested.flatMap { it } // [1, 2, 3, 4, 5, 6]
3. 高阶函数(Higher-Order Functions)
kotlin
// 1. 函数作为参数
fun processNumbers(
numbers: List<Int>,
filter: (Int) -> Boolean,
transform: (Int) -> Int
): List<Int> {
return numbers.filter(filter).map(transform)
}
val result = processNumbers(
numbers = listOf(1, 2, 3, 4, 5),
filter = { it > 2 },
transform = { it * 10 }
) // [30, 40, 50]
// 2. 函数作为返回值
fun getOperation(type: String): (Int, Int) -> Int {
return when (type) {
"add" -> { a, b -> a + b }
"multiply" -> { a, b -> a * b }
else -> { a, b -> a - b }
}
}
val operation = getOperation("add")
println(operation(5, 3)) // 8
// 3. 组合函数
fun compose(f: (Int) -> Int, g: (Int) -> Int): (Int) -> Int {
return { x -> f(g(x)) }
}
val addTwo = { x: Int -> x + 2 }
val timesThree = { x: Int -> x * 3 }
val composed = compose(addTwo, timesThree)
println(composed(5)) // 17 = (5 * 3) + 2
// 4. 带接收者的函数类型
fun buildString(builderAction: StringBuilder.() -> Unit): String {
val sb = StringBuilder()
sb.builderAction()
return sb.toString()
}
val s = buildString {
append("Hello, ")
append("World!")
} // "Hello, World!"
4. 作用域函数(Scope Functions)
kotlin
data class Person(var name: String, var age: Int, var city: String)
val person = Person("Alice", 25, "New York")
// 1. let - 用 it 引用对象,返回 lambda 结果
val nameLength = person.let {
it.name = it.name.capitalize()
it.name.length // 返回这个
}
// 2. run - 用 this 引用对象,返回 lambda 结果
val description = person.run {
age += 1 // 可以直接访问属性
"$name is $age years old from $city" // 返回这个
}
// 3. with - 类似 run,但作为独立函数
with(person) {
println("Processing $name")
city = "London"
}
// 4. apply - 用 this 引用对象,返回对象本身
val modifiedPerson = person.apply {
name = "Bob"
age = 30
} // 返回 person 对象本身
// 5. also - 用 it 引用对象,返回对象本身
val personCopy = person.also {
println("Before: $it")
it.age = 26
}.also {
println("After: $it")
}
5. Lambda 的特殊语法
kotlin
// 1. 最后参数是 lambda 时可以放到括号外
fun executeWithDelay(delay: Long, action: () -> Unit) {
Thread.sleep(delay)
action()
}
// 传统调用
executeWithDelay(1000, { println("Hello") })
// 简化调用(推荐)
executeWithDelay(1000) {
println("Hello")
}
// 2. 如果 lambda 是唯一参数,可以省略括号
listOf(1, 2, 3).forEach { println(it) }
// 3. 带标签的 return
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@forEach // 只从这个 lambda 返回
println(it)
}
// 输出: 1 2 4 5
// 4. 匿名函数(类似 lambda,但 return 行为不同)
listOf(1, 2, 3).forEach(fun(value) {
if (value == 2) return // 从匿名函数返回,继续循环
println(value)
})
// 输出: 1 3
6. 实用示例
kotlin
// 1. DSL 构建器
class HTML {
fun body() { println("Creating body") }
fun div(block: Div.() -> Unit) { Div().apply(block) }
}
class Div {
fun p(text: String) { println("Paragraph: $text") }
fun a(href: String, text: String) { println("Link: <a href='$href'>$text</a>") }
}
fun html(block: HTML.() -> Unit): HTML {
return HTML().apply(block)
}
html {
body()
div {
p("Hello World")
a("https://kotlinlang.org", "Kotlin")
}
}
// 2. 缓存计算结果
fun <T, R> memoize(fn: (T) -> R): (T) -> R {
val cache = mutableMapOf<T, R>()
return { key ->
cache.getOrPut(key) { fn(key) }
}
}
val expensiveCalculation = memoize { n: Int ->
println("Calculating for $n")
// 模拟耗时计算
(1..n).sum()
}
println(expensiveCalculation(5)) // 计算并缓存
println(expensiveCalculation(5)) // 直接使用缓存
7. 函数引用
kotlin
// 1. 函数引用
fun isEven(n: Int) = n % 2 == 0
val numbers = listOf(1, 2, 3, 4, 5)
// 使用函数引用
val evens = numbers.filter(::isEven)
// 2. 属性引用
data class User(val name: String, val age: Int)
val users = listOf(User("Alice", 25), User("Bob", 30))
// 按属性引用排序
val sortedByName = users.sortedBy(User::name)
val ages = users.map(User::age)
// 3. 构造函数引用
class Person(val name: String)
val createPerson = ::Person
val person = createPerson("Charlie")
// 4. 绑定函数引用
val alice = User("Alice", 25)
val isAliceAdult = alice::isAdult
println(isAliceAdult()) // true
fun User.isAdult() = age >= 18
最佳实践
- 优先使用表达式函数体:当函数体很简单时
- 合理使用默认参数:减少重载函数数量
- 善用作用域函数:让代码更简洁清晰
- 链式调用时考虑性能:避免创建过多中间集合
- 使用函数引用:提高代码可读性
- 内联高阶函数:减少 lambda 开销
- 注意 lambda 中的返回行为:使用标签或匿名函数控制
Kotlin 的函数和 lambda 表达式是其函数式编程能力的核心,它们使代码更加简洁、表达力更强,并且支持多种编程范式。