Kotlin Lambda表达式深入应用
Lambda表达式是Kotlin函数式编程的核心特性之一,它让代码更简洁、更具表达力。下面我将从基础到高级,深入探讨Lambda的应用。
1. Lambda基础语法
基本Lambda表达式
// 传统方式
val sum = { x: Int, y: Int -> x + y }
// 类型推断
val sum: (Int, Int) -> Int = { x, y -> x + y }
// 调用
println(sum(3, 5)) // 输出: 8
Lambda作为参数
fun processNumbers(numbers: List<Int>, processor: (Int) -> Int): List<Int> {
return numbers.map(processor)
}
val result = processNumbers(listOf(1, 2, 3)) { it * 2 }
// 结果: [2, 4, 6]
2. 高级Lambda特性
带接收者的Lambda (DSL构建)
// 定义HTML构建器
class Html {
private val children = mutableListOf<String>()
fun body(init: Html.() -> Unit) {
val bodyContent = Html().apply(init)
children.add("<body>${bodyContent.children.joinToString("")}</body>")
}
fun div(init: Html.() -> Unit) {
val divContent = Html().apply(init)
children.add("<div>${divContent.children.joinToString("")}</div>")
}
fun text(content: String) {
children.add(content)
}
override fun toString(): String = children.joinToString("")
}
// 使用
val html = Html().apply {
body {
div {
text("Hello, Kotlin!")
}
}
}
Lambda与集合操作
data class Person(val name: String, val age: Int, val city: String)
val people = listOf(
Person("Alice", 29, "New York"),
Person("Bob", 31, "San Francisco"),
Person("Charlie", 25, "New York"),
Person("Diana", 35, "Chicago")
)
// 链式操作
val result = people
.filter { it.city == "New York" }
.sortedByDescending { it.age }
.groupBy { it.age > 30 }
.mapValues { (key, value) -> value.map { it.name } }
// 自定义集合操作
fun <T> List<T>.filterIndexed(predicate: (Int, T) -> Boolean): List<T> {
val result = mutableListOf<T>()
forEachIndexed { index, value ->
if (predicate(index, value)) result.add(value)
}
return result
}
val filtered = listOf(1, 2, 3, 4, 5).filterIndexed { index, value ->
index % 2 == 0 && value > 2
}
3. Lambda性能优化
内联函数
// 内联函数避免Lambda开销
inline fun <T> measureTime(block: () -> T): Pair<T, Long> {
val start = System.nanoTime()
val result = block()
val end = System.nanoTime()
return result to (end - start)
}
// 使用
val (result, time) = measureTime {
// 耗时操作
Thread.sleep(1000)
"Done"
}
非内联的crossinline和noinline
// crossinline - 禁止非局部返回
inline fun runAsync(crossinline block: () -> Unit) {
Thread {
block() // 这里不能使用return
}.start()
}
// noinline - 指定不内联某个Lambda
inline fun process(
onSuccess: () -> Unit,
noinline onError: (Exception) -> Unit
) {
try {
// 操作
onSuccess()
} catch (e: Exception) {
// onError不会被内联
onError(e)
}
}
4. Lambda的实用模式
缓存/记忆化模式
fun <T, R> memoize(fn: (T) -> R): (T) -> R {
val cache = mutableMapOf<T, R>()
return { key ->
cache.getOrPut(key) { fn(key) }
}
}
// 使用
val expensiveCalculation = { n: Int ->
Thread.sleep(1000)
n * n
}
val memoizedCalculation = memoize(expensiveCalculation)
println(memoizedCalculation(5)) // 计算并缓存
println(memoizedCalculation(5)) // 从缓存获取
函数柯里化
fun <A, B, C> curry(f: (A, B) -> C): (A) -> (B) -> C =
{ a -> { b -> f(a, b) } }
fun <A, B, C, D> curry(f: (A, B, C) -> D): (A) -> (B) -> (C) -> D =
{ a -> { b -> { c -> f(a, b, c) } } }
// 使用
val add = { a: Int, b: Int -> a + b }
val curriedAdd = curry(add)
val add5 = curriedAdd(5)
println(add5(3)) // 8
5. Lambda与协程结合
import kotlinx.coroutines.*
// Lambda作为协程构建器参数
fun launchMultipleTasks() = runBlocking {
val jobs = List(10) { index ->
launch {
delay((1000L..2000L).random())
println("Task $index completed on ${Thread.currentThread().name}")
}
}
jobs.forEach { it.join() }
}
// 高阶函数与协程
suspend fun <T, R> withTimeoutOrNull(
timeout: Long,
block: suspend () -> T,
onTimeout: suspend () -> R
): Any? = coroutineScope {
try {
withTimeout(timeout) { block() }
} catch (e: TimeoutCancellationException) {
onTimeout()
}
}
6. DSL设计模式
// SQL查询DSL
class QueryBuilder {
private var selectColumns = mutableListOf<String>()
private var fromTable: String? = null
private var whereClause: String? = null
fun select(vararg columns: String) {
selectColumns.addAll(columns)
}
fun from(table: String) {
fromTable = table
}
fun where(condition: String) {
whereClause = condition
}
fun build(): String {
val columns = if (selectColumns.isEmpty()) "*" else selectColumns.joinToString(", ")
val where = whereClause?.let { " WHERE $it" } ?: ""
return "SELECT $columns FROM ${fromTable ?: "unknown"}$where"
}
}
// 使用DSL
fun query(init: QueryBuilder.() -> Unit): QueryBuilder {
return QueryBuilder().apply(init)
}
val sql = query {
select("id", "name", "email")
from("users")
where("age > 18")
}.build()
7. Lambda与类型安全构建器
// 类型安全的HTML构建器
open class Tag(val name: String) {
private val children = mutableListOf<Tag>()
protected val attributes = mutableMapOf<String, String>()
operator fun String.unaryPlus() {
children.add(TextTag(this))
}
fun <T : Tag> initTag(tag: T, init: T.() -> Unit): T {
tag.init()
children.add(tag)
return tag
}
override fun toString(): String {
return "<$name${attributes.entries.joinToString("") { " ${it.key}=\"${it.value}\"" }}" +
if (children.isEmpty()) "/>"
else ">${children.joinToString("")}</$name>"
}
}
class TextTag(val text: String) : Tag("") {
override fun toString(): String = text
}
fun html(init: HTML.() -> Unit): HTML {
return HTML().apply(init)
}
class HTML : Tag("html") {
fun head(init: Head.() -> Unit) = initTag(Head(), init)
fun body(init: Body.() -> Unit) = initTag(Body(), init)
}
class Head : Tag("head") {
fun title(init: Title.() -> Unit) = initTag(Title(), init)
}
class Title : Tag("title")
class Body : Tag("body") {
fun h1(init: H1.() -> Unit) = initTag(H1(), init)
fun p(init: P.() -> Unit) = initTag(P(), init)
}
class H1 : Tag("h1")
class P : Tag("p")
// 使用
val document = html {
head {
title { +"Kotlin DSL" }
}
body {
h1 { +"Hello Kotlin DSL" }
p {
+"This is a paragraph"
}
}
}
8. 性能考虑和最佳实践
避免不必要的Lambda创建
// 不好: 在循环中重复创建Lambda
fun processList(items: List<String>) {
items.forEach { item ->
// 每次循环都创建新的Lambda
processItem { println(item) }
}
}
// 好: 复用Lambda
fun processListOptimized(items: List<String>) {
val processor: (String) -> Unit = { item ->
processItem { println(item) }
}
items.forEach(processor)
}
使用序列进行惰性求值
val largeList = (1..1_000_000).toList()
// 急切求值 - 创建中间集合
val result1 = largeList
.filter { it % 2 == 0 } // 创建500k元素的列表
.map { it * 2 } // 再次创建500k元素的列表
.take(10) // 只取前10个
// 惰性求值 - 无中间集合
val result2 = largeList.asSequence()
.filter { it % 2 == 0 } // 惰性过滤
.map { it * 2 } // 惰性映射
.take(10) // 只处理前10个元素
.toList()
总结
Kotlin的Lambda表达式提供了强大的函数式编程能力:
- 简洁性:减少样板代码,提高可读性
- 表达力:支持DSL设计,创建领域特定语言
- 函数组合:支持高阶函数和函数组合
- 性能优化:通过内联函数减少运行时开销
- 类型安全:编译时类型检查保证安全性
掌握Lambda的高级用法可以让你编写出更优雅、更高效的Kotlin代码。实际应用中,建议根据具体场景选择合适的技术,避免过度设计。