Kotlin 函数式编程全面指南
Kotlin 完美融合了面向对象和函数式编程范式,提供了强大且简洁的函数式编程能力。
1. 核心概念
1.1 函数作为一等公民
// 函数可以作为变量
val add: (Int, Int) -> Int = { a, b -> a + b }
// 函数可以作为参数
fun calculate(x: Int, y: Int, operation: (Int, Int) -> Int): Int {
return operation(x, y)
}
// 函数可以作为返回值
fun getMultiplier(factor: Int): (Int) -> Int {
return { value -> value * factor }
}
fun main() {
println(calculate(5, 3, add)) // 8
val triple = getMultiplier(3)
println(triple(5)) // 15
}
1.2 不可变性
// 不可变集合
val immutableList = listOf(1, 2, 3)
val immutableMap = mapOf("a" to 1, "b" to 2)
// 可变集合(需要时使用)
val mutableList = mutableListOf(1, 2, 3)
// 数据类默认是不可变的
data class User(val name: String, val age: Int)
fun main() {
val user = User("Alice", 30)
// user.age = 31 // 编译错误
val updatedUser = user.copy(age = 31) // 创建新实例
}
2. Lambda 表达式与高阶函数
2.1 Lambda 语法
// 完整语法
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
// 类型推断
val sum2 = { x: Int, y: Int -> x + y }
// 单参数时可用 it
val square: (Int) -> Int = { it * it }
// 多行 Lambda
val processString = { str: String ->
val trimmed = str.trim()
trimmed.uppercase()
}
fun main() {
println(sum(3, 4)) // 7
println(square(5)) // 25
println(processString(" hello ")) // HELLO
}
2.2 高阶函数实践
// 接受函数作为参数
fun List<Int>.customFilter(predicate: (Int) -> Boolean): List<Int> {
val result = mutableListOf<Int>()
for (item in this) {
if (predicate(item)) {
result.add(item)
}
}
return result
}
// 返回函数
fun createLogger(prefix: String): (String) -> Unit {
return { message -> println("[$prefix] $message") }
}
// 内联函数优化
inline fun measureTime(block: () -> Unit): Long {
val start = System.nanoTime()
block()
return System.nanoTime() - start
}
fun main() {
val numbers = listOf(1, 2, 3, 4, 5)
val evenNumbers = numbers.customFilter { it % 2 == 0 }
println(evenNumbers) // [2, 4]
val debugLogger = createLogger("DEBUG")
debugLogger("Application started")
val duration = measureTime {
Thread.sleep(100)
}
println("Time taken: ${duration / 1_000_000}ms")
}
3. 集合函数式操作
3.1 转换操作
fun main() {
val numbers = listOf(1, 2, 3, 4, 5)
// map - 转换每个元素
val squared = numbers.map { it * it }
println(squared) // [1, 4, 9, 16, 25]
// flatMap - 展平嵌套集合
val nested = listOf(listOf(1, 2), listOf(3, 4))
val flattened = nested.flatMap { it }
println(flattened) // [1, 2, 3, 4]
// mapIndexed - 使用索引
val withIndex = numbers.mapIndexed { index, value ->
"Item $index: $value"
}
println(withIndex) // [Item 0: 1, Item 1: 2, ...]
// associate - 创建映射
val squaresMap = numbers.associate { it to it * it }
println(squaresMap) // {1=1, 2=4, 3=9, 4=16, 5=25}
}
3.2 过滤操作
fun main() {
val numbers = (1..10).toList()
// filter - 基本过滤
val evens = numbers.filter { it % 2 == 0 }
// filterNot - 反向过滤
val odds = numbers.filterNot { it % 2 == 0 }
// filterIndexed - 基于索引过滤
val firstHalf = numbers.filterIndexed { index, _ -> index < 5 }
// filterIsInstance - 类型过滤
val mixedList = listOf(1, "two", 3, "four", 5)
val integers = mixedList.filterIsInstance<Int>()
// takeWhile / dropWhile
val takeWhile = numbers.takeWhile { it < 5 } // [1, 2, 3, 4]
val dropWhile = numbers.dropWhile { it < 5 } // [5, 6, 7, 8, 9, 10]
}
3.3 聚合操作
fun main() {
val numbers = listOf(1, 2, 3, 4, 5)
// reduce - 累积操作
val sum = numbers.reduce { acc, value -> acc + value }
println(sum) // 15
// fold - 带初始值的累积
val product = numbers.fold(1) { acc, value -> acc * value }
println(product) // 120
// foldRight - 从右到左
val concatenated = numbers.foldRight("") { value, acc -> "$value$acc" }
println(concatenated) // "54321"
// max/min
val max = numbers.maxOrNull()
val min = numbers.minOrNull()
// sum/sumOf
val total = numbers.sum()
val sumOfSquares = numbers.sumOf { it * it }
// groupBy - 分组
val words = listOf("apple", "banana", "cherry", "date")
val byLength = words.groupBy { it.length }
println(byLength) // {5=[apple], 6=[banana, cherry], 4=[date]}
// partition - 分割
val (evens, odds) = numbers.partition { it % 2 == 0 }
println("Evens: $evens, Odds: $odds")
}
3.4 查找操作
fun main() {
val numbers = listOf(1, 2, 3, 4, 5)
// find - 查找第一个匹配元素
val firstEven = numbers.find { it % 2 == 0 } // 2
// first/last - 带条件
val lastOdd = numbers.last { it % 2 == 1 } // 5
// single - 期望只有一个匹配元素
val single = listOf(5).single { it > 3 } // 5
// any/all/none
val hasEven = numbers.any { it % 2 == 0 } // true
val allPositive = numbers.all { it > 0 } // true
val noNegatives = numbers.none { it < 0 } // true
// count
val evenCount = numbers.count { it % 2 == 0 } // 2
}
4. 序列(Sequences)
序列是惰性求值的集合,适合处理大数据集。
fun main() {
// 创建序列
val sequence1 = sequenceOf(1, 2, 3, 4, 5)
val sequence2 = (1..5).asSequence()
val sequence3 = generateSequence(1) { it + 1 }.take(5)
// 惰性求值示例
val result = (1..1_000_000)
.asSequence()
.filter {
println("Filtering $it")
it % 2 == 0
}
.map {
println("Mapping $it")
it * 2
}
.take(3) // 只处理前3个元素
.toList()
println(result) // [4, 8, 12]
// 无限序列
val fibonacci = sequence {
var a = 0
var b = 1
yield(a)
yield(b)
while (true) {
val next = a + b
yield(next)
a = b
b = next
}
}
val first10Fibonacci = fibonacci.take(10).toList()
println(first10Fibonacci) // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
}
5. 函数组合与柯里化
5.1 函数组合
// 组合函数:f(g(x))
infix fun <A, B, C> ((B) -> C).compose(g: (A) -> B): (A) -> C {
return { x -> this(g(x)) }
}
// 管道操作:g(f(x))
infix fun <A, B, C> ((A) -> B).andThen(f: (B) -> C): (A) -> C {
return { x -> f(this(x)) }
}
fun main() {
val add2 = { x: Int -> x + 2 }
val multiplyBy3 = { x: Int -> x * 3 }
val square = { x: Int -> x * x }
// 组合:square(add2(x))
val addThenSquare = square compose add2
println(addThenSquare(3)) // (3+2)^2 = 25
// 管道:multiplyBy3(square(x))
val squareThenMultiply = square andThen multiplyBy3
println(squareThenMultiply(4)) // (4^2)*3 = 48
// 多函数组合
val pipeline = add2 andThen multiplyBy3 andThen square
println(pipeline(5)) // ((5+2)*3)^2 = 441
}
5.2 柯里化(Currying)
// 柯里化:将多参数函数转换为一系列单参数函数
fun <A, B, C> curry(f: (A, B) -> C): (A) -> (B) -> C {
return { a -> { b -> f(a, b) } }
}
// 反柯里化
fun <A, B, C> uncurry(f: (A) -> (B) -> C): (A, B) -> C {
return { a, b -> f(a)(b) }
}
// 部分应用
fun <A, B, C> partial(f: (A, B) -> C, a: A): (B) -> C {
return { b -> f(a, b) }
}
fun main() {
// 普通多参数函数
val add: (Int, Int) -> Int = { a, b -> a + b }
// 柯里化版本
val curriedAdd = curry(add)
val add5 = curriedAdd(5)
println(add5(3)) // 8
// 部分应用
val multiplyBy10 = partial({ a: Int, b: Int -> a * b }, 10)
println(multiplyBy10(7)) // 70
// 实际应用:配置函数
val createGreeting = { greeting: String, name: String -> "$greeting, $name!" }
val sayHello = partial(createGreeting, "Hello")
val sayHi = partial(createGreeting, "Hi")
println(sayHello("Alice")) // Hello, Alice!
println(sayHi("Bob")) // Hi, Bob!
}
6. 递归与尾递归优化
// 普通递归
fun factorial(n: Int): Int {
return if (n <= 1) 1 else n * factorial(n - 1)
}
// 尾递归优化
tailrec fun factorialTailRec(n: Int, accumulator: Int = 1): Int {
return if (n <= 1) accumulator
else factorialTailRec(n - 1, n * accumulator)
}
// 尾递归遍历树结构
sealed class Tree<T> {
data class Node<T>(val value: T, val left: Tree<T>, val right: Tree<T>) : Tree<T>()
object Empty : Tree<Nothing>()
}
tailrec fun <T> searchTree(tree: Tree<T>, target: T): Boolean = when (tree) {
is Tree.Empty -> false
is Tree.Node -> {
if (tree.value == target) true
else searchTree(tree.left, target) || searchTree(tree.right, target)
}
}
fun main() {
println(factorial(5)) // 120
println(factorialTailRec(5)) // 120
val tree = Tree.Node(1,
Tree.Node(2, Tree.Empty, Tree.Empty),
Tree.Node(3, Tree.Empty, Tree.Empty)
)
println(searchTree(tree, 2)) // true
println(searchTree(tree, 4)) // false
}
7. 函数式错误处理
7.1 Either 模式
sealed class Either<out L, out R> {
data class Left<out L>(val value: L) : Either<L, Nothing>()
data class Right<out R>(val value: R) : Either<Nothing, R>()
fun <T> fold(leftOp: (L) -> T, rightOp: (R) -> T): T = when (this) {
is Left -> leftOp(value)
is Right -> rightOp(value)
}
fun isLeft(): Boolean = this is Left
fun isRight(): Boolean = this is Right
}
// Either 扩展函数
fun <L, R, T> Either<L, R>.map(f: (R) -> T): Either<L, T> = when (this) {
is Either.Left -> Either.Left(value)
is Either.Right -> Either.Right(f(value))
}
fun <L, R, T> Either<L, R>.flatMap(f: (R) -> Either<L, T>): Either<L, T> = when (this) {
is Either.Left -> Either.Left(value)
is Either.Right -> f(value)
}
// 使用示例
fun parseNumber(str: String): Either<String, Int> {
return try {
Either.Right(str.toInt())
} catch (e: NumberFormatException) {
Either.Left("Failed to parse: $str")
}
}
fun divide(a: Int, b: Int): Either<String, Int> {
return if (b == 0) {
Either.Left("Division by zero")
} else {
Either.Right(a / b)
}
}
fun main() {
val result = parseNumber("10")
.flatMap { a -> parseNumber("2").flatMap { b -> divide(a, b) } }
result.fold(
leftOp = { error -> println("Error: $error") },
rightOp = { value -> println("Result: $value") }
) // Result: 5
}
7.2 Result 类型
typealias Result<T> = Either<String, T>
fun <T, R> Result<T>.mapResult(transform: (T) -> R): Result<R> {
return when (this) {
is Either.Left -> Either.Left(value)
is Either.Right -> Either.Right(transform(value))
}
}
fun <T, R> Result<T>.flatMapResult(transform: (T) -> Result<R>): Result<R> {
return when (this) {
is Either.Left -> Either.Left(value)
is Either.Right -> transform(value)
}
}
// 管道操作
infix fun <T, R> Result<T>.`then`(transform: (T) -> Result<R>): Result<R> {
return flatMapResult(transform)
}
// 使用示例
fun processUserInput(input: String): Result<Int> {
return parseNumber(input)
.then { validatePositive(it) }
.then { processValue(it) }
}
fun validatePositive(n: Int): Result<Int> {
return if (n > 0) Either.Right(n)
else Either.Left("Number must be positive")
}
fun processValue(n: Int): Result<Int> {
return Either.Right(n * 2)
}
fun main() {
val results = listOf("10", "-5", "abc")
results.forEach { input ->
val result = processUserInput(input)
result.fold(
leftOp = { println("Input '$input' failed: $it") },
rightOp = { println("Input '$input' result: $it") }
)
}
}
8. 函数式编程设计模式
8.1 管道模式
class Pipeline<T>(private val value: T) {
fun <R> pipe(transform: (T) -> R): Pipeline<R> {
return Pipeline(transform(value))
}
fun get(): T = value
}
// 扩展函数版本
fun <T> T.pipe(): Pipeline<T> = Pipeline(this)
infix fun <T, R> Pipeline<T>.`|`(transform: (T) -> R): Pipeline<R> {
return pipe(transform)
}
fun main() {
val result = " hello world "
.pipe()
.pipe { it.trim() }
.pipe { it.uppercase() }
.pipe { it.split(" ") }
.pipe { it.joinToString("-") }
.get()
println(result) // HELLO-WORLD
// 使用中缀操作符
val result2 = "Kotlin"
.pipe()
| { it.reversed() }
| { it.uppercase() }
| { "Result: $it" }
.get()
println(result2) // Result: NILTOK
}
8.2 Option 模式(类似 Optional)
sealed class Option<out T> {
data class Some<T>(val value: T) : Option<T>()
object None : Option<Nothing>()
companion object {
fun <T> of(value: T?): Option<T> {
return if (value != null) Some(value) else None
}
}
fun <R> map(transform: (T) -> R): Option<R> = when (this) {
is Some -> Some(transform(value))
None -> None
}
fun <R> flatMap(transform: (T) -> Option<R>): Option<R> = when (this) {
is Some -> transform(value)
None -> None
}
fun getOrElse(default: () -> T): T = when (this) {
is Some -> value
None -> default()
}
fun orElse(alternative: () -> Option<T>): Option<T> = when (this) {
is Some -> this
None -> alternative()
}
}
// 使用示例
data class User(val name: String, val email: String?)
fun getUserName(userId: Int): Option<User> {
val users = mapOf(
1 to User("Alice", "alice@example.com"),
2 to User("Bob", null)
)
return Option.of(users[userId])
}
fun main() {
val email1 = getUserName(1)
.flatMap { user -> Option.of(user.email) }
.getOrElse { "No email" }
val email2 = getUserName(2)
.flatMap { user -> Option.of(user.email) }
.getOrElse { "No email" }
println("User 1 email: $email1") // alice@example.com
println("User 2 email: $email2") // No email
}
9. 性能优化
// 1. 使用 inline 减少函数对象开销
inline fun <T> List<T>.fastFilter(predicate: (T) -> Boolean): List<T> {
val result = mutableListOf<T>()
for (item in this) {
if (predicate(item)) {
result.add(item)
}
}
return result
}
// 2. 使用 sequence 处理大数据集
fun processLargeDataset() {
val largeList = (1..1_000_000).toList()
// 普通操作(会创建中间集合)
val result1 = largeList
.filter { it % 2 == 0 }
.map { it * 2 }
.take(1000)
// 序列操作(惰性求值,更高效)
val result2 = largeList.asSequence()
.filter { it % 2 == 0 }
.map { it * 2 }
.take(1000)
.toList()
}
// 3. 避免重复计算
fun memoize(function: (Int) -> Int): (Int) -> Int {
val cache = mutableMapOf<Int, Int>()
return { input ->
cache.getOrPut(input) { function(input) }
}
}
fun expensiveCalculation(n: Int): Int {
Thread.sleep(100) // 模拟耗时计算
return n * n
}
fun main() {
val memoizedCalc = memoize(::expensiveCalculation)
println(memoizedCalc(5)) // 第一次计算,耗时
println(memoizedCalc(5)) // 从缓存读取,快速
}
10. 实战案例
10.1 数据转换管道
data class Person(val name: String, val age: Int, val city: String)
fun main() {
val people = listOf(
Person("Alice", 25, "New York"),
Person("Bob", 30, "London"),
Person("Charlie", 28, "New York"),
Person("David", 35, "Paris"),
Person("Eve", 22, "London")
)
val result = people
.filter { it.age > 25 }
.groupBy { it.city }
.mapValues { (_, peopleInCity) ->
peopleInCity
.sortedByDescending { it.age }
.map { it.name }
.take(2)
}
.filter { (_, names) -> names.size >= 2 }
println(result)
// {New York=[Charlie, Alice], London=[Bob, Eve]}
}
10.2 函数式配置构建器
class DatabaseConfig(
val url: String,
val username: String,
val password: String,
val poolSize: Int
) {
data class Builder(
var url: String = "",
var username: String = "",
var password: String = "",
var poolSize: Int = 10
) {
fun build(): DatabaseConfig {
require(url.isNotBlank()) { "URL is required" }
require(username.isNotBlank()) { "Username is required" }
require(password.isNotBlank()) { "Password is required" }
require(poolSize > 0) { "Pool size must be positive" }
return DatabaseConfig(url, username, password, poolSize)
}
}
}
// 使用 DSL 风格的构建器
fun databaseConfig(configure: DatabaseConfig.Builder.() -> Unit): DatabaseConfig {
val builder = DatabaseConfig.Builder()
builder.configure()
return builder.build()
}
fun main() {
val config = databaseConfig {
url = "jdbc:mysql://localhost:3306/mydb"
username = "admin"
password = "secret"
poolSize = 20
}
println("Connected to ${config.url}")
}
总结
Kotlin 函数式编程优势:
- 简洁性 - 减少样板代码
- 表达力 - 代码更接近业务逻辑
- 安全性 - 不可变性减少副作用
- 可测试性 - 纯函数易于测试
- 并发友好 - 不可变数据减少竞态条件
最佳实践:
- 优先使用不可变数据
- 使用标准库函数式操作
- 对于大数据集使用 Sequence
- 合理使用 inline 优化性能
- 结合面向对象和函数式编程的优势
Kotlin 的函数式编程特性让你能够编写更简洁、更安全、更易维护的代码,同时保持与 Java 的完全互操作性。