Kotlin函数一

3.1 Lambda 表达式基础

3.1.1 函数式编程的核心理念

什么是函数式编程

  • 函数是第一等公民(First-class citizen)
  • 不可变性(Immutability)
  • 纯函数(Pure function)
  • 高阶函数(Higher-order function)

为什么需要函数式编程

kotlin 复制代码
// 命令式编程 - 关注"怎么做"
fun filterAdults(users: List<User>): List<User> {
    val result = mutableListOf<User>()
    for (user in users) {
        if (user.age >= 18) {
            result.add(user)
        }
    }
    return result
}

// 函数式编程 - 关注"做什么"
fun filterAdultsFunctional(users: List<User>): List<User> {
    return users.filter { it.age >= 18 }
}

对比分析

方面 命令式编程 函数式编程
代码量 较多 较少
可读性 需要理解循环逻辑 接近自然语言
可维护性 需要手动管理状态 无状态,易于维护
可测试性 需要模拟完整流程 纯函数易于测试
并发安全 需要同步机制 天然线程安全

3.1.2 Lambda 语法

Lambda 表达式的基本语法

kotlin 复制代码
// 完整语法
val sum: (Int, Int) -> Int = { a: Int, b: Int -> a + b }

// 简化语法(类型推断)
val sum2 = { a: Int, b: Int -> a + b }

// 单参数(可以省略括号)
val square: (Int) -> Int = { it * it }

// 无参数
val greet: () -> Unit = { println("Hello") }

// 多行 Lambda
val calculate: (Int, Int) -> Pair<Int, Int> = { a, b ->
    val sum = a + b
    val product = a * b
    Pair(sum, product)
}

Lambda 表达式的特性

kotlin 复制代码
// 1. 可以赋值给变量
val add = { a: Int, b: Int -> a + b }
println(add(3, 5)) // 输出:8

// 2. 可以作为参数传递
fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
    return operation(a, b)
}

val result = calculate(10, 5) { a, b -> a + b } // 输出:15

// 3. 可以作为返回值
fun createAdder(addend: Int): (Int) -> Int {
    return { number -> number + addend }
}

val addFive = createAdder(5)
println(addFive(10)) // 输出:15

//上面代码通过工具可以看到
@NotNull
public static final Function1 createAdder(int addend) {
    return BookKt::createAdder$lambda$0;
}
//addFive方法
private static final int createAdder$lambda$0(int $addend, int number) {
    return number + $addend;
}

3.1.3 尾递归优化

递归的问题:栈溢出风险。

kotlin 复制代码
// 普通递归 - 栈溢出风险---//3*2*1*1
fun factorial(n: Long): Long {
    return if (n == 0L) 1 else n * factorial(n - 1)
}

// factorial(100000) // 栈溢出

尾递归的条件

  1. 递归调用是函数的最后一步操作
  2. 必须使用 tailrec 关键字标记
  3. 不能在 try-catch-finally 块中

实际应用

kotlin 复制代码
// 尾递归优化 - 深度优先搜索
tailrec fun findTarget(
    list: List<Int>,
    target: Int,
    index: Int = 0
): Int? {
    return when {
        index >= list.size -> null
        list[index] == target -> index
        else -> findTarget(list, target, index + 1)
    }
}

val list = (1..100000).toList()
println(findTarget(list, 50000)) // 输出:49999

3.1.4 匿名函数

匿名函数 vs Lambda 表达式

kotlin 复制代码
// Lambda 表达式
val lambda1: (Int, Int) -> Int = { a, b -> a + b }

// 匿名函数
val lambda2: (Int, Int) -> Int = fun(a: Int, b: Int): Int {
    return a + b
}

// 简化的匿名函数
val lambda3 = fun(a: Int, b: Int): Int = a + b

匿名函数的特性

kotlin 复制代码
// 1. 显式返回类型
val lambda4 = fun(a: Int, b: Int): Int {
    return a + b
}

// 2. 支持返回值类型推断
val lambda5 = fun(a: Int, b: Int) = a + b

// 3. 非局部返回(return 会退出包含它的函数)
fun example() {
    val list = listOf(1, 2, 3, 4, 5)
    list.forEach {
        if (it == 3) return // 退出 example 函数
        println(it)
    }
    println("这行不会执行")
}
example() // 输出:1 2

// 使用匿名函数避免非局部返回
fun example2() {
    val list = listOf(1, 2, 3, 4, 5)
    list.forEach(fun(it) {
        if (it == 3) return@forEach // 只退出 lambda
        println(it)
    })
    println("这行会执行")
}
example2() // 输出:1 2 4 5 这行会执行

3.2 高阶函数与函数类型

3.2.1 函数类型的定义

函数类型语法

kotlin 复制代码
// 基本语法:(参数列表) -> 返回值类型
val sum: (Int, Int) -> Int = { a, b -> a + b }
val greet: () -> Unit = { println("Hello") }
val transform: (String) -> String = { it.uppercase() }

// 无返回值(Unit)
val printInt: (Int) -> Unit = { println(it) }

// 可空函数类型
val nullableFunction: ((Int) -> Int)? = null

// 带接收者的函数类型
val String.lastChar: () -> Char = { this[this.length - 1] }

3.2.2 函数作为参数

高阶函数示例

kotlin 复制代码
// 函数作为参数
fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
    return operation(a, b)
}

// 使用
val sum = calculate(10, 5) { a, b -> a + b }
val difference = calculate(10, 5) { a, b -> a - b }
val product = calculate(10, 5) { a, b -> a * b }

println(sum) // 输出:15
println(difference) // 输出:5
println(product) // 输出:50

实际应用 - 过滤器

kotlin 复制代码
// 高阶函数 - 过滤器
fun <T> filterList(list: List<T>, predicate: (T) -> Boolean): List<T> {
    val result = mutableListOf<T>()
    for (item in list) {
        if (predicate(item)) {
            result.add(item)
        }
    }
    return result
}

// 使用
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val evenNumbers = filterList(numbers) { it % 2 == 0 }
val oddNumbers = filterList(numbers) { it % 2 != 0 }
val greaterThanFive = filterList(numbers) { it > 5 }

println(evenNumbers) // 输出:[2, 4, 6, 8, 10]
println(oddNumbers) // 输出:[1, 3, 5, 7, 9]
println(greaterThanFive) // 输出:[6, 7, 8, 9, 10]

3.2.3 函数作为返回值

函数工厂模式

kotlin 复制代码
// 函数作为返回值
fun createOperation(operation: String): (Int, Int) -> Int {
    return when (operation) {
        "add" -> { a, b -> a + b }
        "subtract" -> { a, b -> a - b }
        "multiply" -> { a, b -> a * b }
        "divide" -> { a, b -> a / b }
        else -> { _, _ -> 0 }
    }
}

// 使用
val add = createOperation("add")
val subtract = createOperation("subtract")

println(add(10, 5)) // 输出:15
println(subtract(10, 5)) // 输出:5

闭包(Closure)

kotlin 复制代码
// 闭包 - 函数可以访问外部变量
fun createCounter(start: Int = 0): () -> Int {
    var count = start
    return { ++count }
}

val counter1 = createCounter()
println(counter1()) // 输出:1
println(counter1()) // 输出:2
println(counter1()) // 输出:3

val counter2 = createCounter(10)
println(counter2()) // 输出:11
println(counter2()) // 输出:12

3.2.4 常用高阶函数

let 函数

kotlin 复制代码
// let - 在非空时执行操作
val name: String? = "张三"

name?.let {
    println("名字长度:${it.length}") // 输出:名字长度:2
}

// 用于链式调用
val result = "hello"
    .let { it.uppercase() }
    .let { it.reversed() }
    .let { "$it!" }
println(result) // 输出:OLLEH!

also 函数

kotlin 复制代码
// also - 执行操作并返回对象本身
val user = User("1", "张三", "zhang@example.com", 25)
    .also {
        println("创建用户:${it.name}") // 输出:创建用户:张三
    }
    .also {
        it.email = "new_email@example.com"
    }

println(user.email) // 输出:new_email@example.com

apply 函数

kotlin 复制代码
// apply - 配置对象并返回对象本身
val dialog = AlertDialog.Builder(this)
    .apply {
        setTitle("提示")
        setMessage("确定要删除吗?")
        setPositiveButton("确定") { _, _ ->
            // 点击确定
        }
        setNegativeButton("取消", null)
    }
    .create()

with 函数

kotlin 复制代码
// with - 在对象上下文中执行多个操作
val user = User("1", "张三", "zhang@example.com", 25)

with(user) {
    println("姓名:$name") // 输出:姓名:张三
    println("年龄:$age") // 输出:年龄:25
    println("邮箱:$email") // 输出:邮箱:zhang@example.com
}

run 函数

kotlin 复制代码
// run - 结合 let 和 with 的功能
val result = "hello".run {
    println("原字符串:$this") // 输出:原字符串:hello
    uppercase().reversed() // 返回 OLLEH
}
println(result) // 输出:OLLEH

// 用于初始化对象
val user = run {
    val id = "1"
    val name = "张三"
    User(id, name, "$name@example.com", 25)
}

takeIf 和 takeUnless

kotlin 复制代码
// takeIf - 满足条件时返回对象,否则返回 null
val number = 10
val evenNumber = number.takeIf { it % 2 == 0 }
val oddNumber = number.takeIf { it % 2 != 0 }

println(evenNumber) // 输出:10
println(oddNumber) // 输出:null

// takeUnless - 不满足条件时返回对象
val validNumber = number.takeUnless { it < 0 }
val invalidNumber = number.takeUnless { it >= 0 }

println(validNumber) // 输出:10
println(invalidNumber) // 输出:null

repeat 函数

kotlin 复制代码
// repeat - 重复执行操作
repeat(3) {
    println("重复执行第 ${it + 1} 次")
}
// 输出:
// 重复执行第 1 次
// 重复执行第 2 次
// 重复执行第 3 次

3.3 集合操作符实战

3.3.1 基础操作符

map - 转换元素

kotlin 复制代码
val numbers = listOf(1, 2, 3, 4, 5)

// 转换为平方
val squares = numbers.map { it * it }
println(squares) // 输出:[1, 4, 9, 16, 25]

// 转换为字符串
val strings = numbers.map { "数字:$it" }
println(strings) // 输出:[数字:1, 数字:2, 数字:3, 数字:4, 数字:5]

// 转换为对象
val users = numbers.map { User(it.toString(), "用户$it", "user$it@example.com", it + 18) }
println(users) // 输出:[User(id=1, name=用户1, ...), ...]

filter - 过滤元素

kotlin 复制代码
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]

// 过滤大于 5 的数
val greaterThanFive = numbers.filter { it > 5 }
println(greaterThanFive) // 输出:[6, 7, 8, 9, 10]

// 过滤非空字符串
val strings = listOf("Hello", null, "World", null, "Kotlin")
val nonNullStrings = strings.filterNotNull()
println(nonNullStrings) // 输出:[Hello, World, Kotlin]

filterNot - 过滤不满足条件的元素

kotlin 复制代码
val numbers = listOf(1, 2, 3, 4, 5)
val notEvenNumbers = numbers.filterNot { it % 2 == 0 }
println(notEvenNumbers) // 输出:[1, 3, 5]

3.3.2 聚合操作符

reduce - 归约

kotlin 复制代码
val numbers = listOf(1, 2, 3, 4, 5)

// 求和
val sum = numbers.reduce { acc, number -> acc + number }
println(sum) // 输出:15

// 求积
val product = numbers.reduce { acc, number -> acc * number }
println(product) // 输出:120

// 查找最大值
val max = numbers.reduce { acc, number -> if (acc > number) acc else number }
println(max) // 输出:5

fold - 折叠(带初始值的归约)

kotlin 复制代码
val numbers = listOf(1, 2, 3, 4, 5)

// 求和(初始值为 0)
val sum = numbers.fold(0) { acc, number -> acc + number }
println(sum) // 输出:15

// 拼接字符串(初始值为空字符串)
val result = numbers.fold("") { acc, number -> "$acc$number" }
println(result) // 输出:12345

// 构建字符串(带分隔符)
val formatted = numbers.fold("数字:") { acc, number -> "$acc$number, " }
println(formatted) // 输出:数字:1, 2, 3, 4, 5,

sum, average, max, min

kotlin 复制代码
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

println(numbers.sum()) // 输出:55
println(numbers.average()) // 输出:5.5
println(numbers.maxOrNull()) // 输出:10
println(numbers.minOrNull()) // 输出:1

count - 计数

kotlin 复制代码
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

// 总数
println(numbers.count()) // 输出:10

// 偶数数量
println(numbers.count { it % 2 == 0 }) // 输出:5

// 大于 5 的数量
println(numbers.count { it > 5 }) // 输出:5

3.3.3 查找操作符

find - 查找第一个满足条件的元素

kotlin 复制代码
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

// 查找第一个偶数
val firstEven = numbers.find { it % 2 == 0 }
println(firstEven) // 输出:2

// 查找第一个大于 5 的数
val firstGreaterThanFive = numbers.find { it > 5 }
println(firstGreaterThanFive) // 输出:6

findLast - 查找最后一个满足条件的元素

kotlin 复制代码
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

// 查找最后一个偶数
val lastEven = numbers.findLast { it % 2 == 0 }
println(lastEven) // 输出:10

first 和 last - 获取第一个/最后一个元素

kotlin 复制代码
val numbers = listOf(1, 2, 3, 4, 5)

println(numbers.first()) // 输出:1
println(numbers.last()) // 输出:5

// 带条件的 first
println(numbers.first { it > 3 }) // 输出:4

// 带条件的 last
println(numbers.last { it < 5 }) // 输出:4

any, all, none - 检查元素

kotlin 复制代码
val numbers = listOf(1, 2, 3, 4, 5)

// 是否有任何元素满足条件
println(numbers.any { it % 2 == 0 }) // 输出:true
println(numbers.any { it > 10 }) // 输出:false

// 是否所有元素都满足条件
println(numbers.all { it > 0 }) // 输出:true
println(numbers.all { it < 5 }) // 输出:false

// 是否没有元素满足条件
println(numbers.none { it > 10 }) // 输出:true
println(numbers.none { it < 5 }) // 输出:false

3.3.4 分组操作符

groupBy - 分组

kotlin 复制代码
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

// 按奇偶分组
val groupedByParity = numbers.groupBy { if (it % 2 == 0) "偶数" else "奇数" }
println(groupedByParity)
// 输出:{奇数=[1, 3, 5, 7, 9], 偶数=[2, 4, 6, 8, 10]}

// 按范围分组
val groupedByRange = numbers.groupBy { when {
    it <= 3 -> "小"
    it <= 6 -> "中"
    else -> "大"
}}
println(groupedByRange)
// 输出:{小=[1, 2, 3], 中=[4, 5, 6], 大=[7, 8, 9, 10]}

partition - 分区

kotlin 复制代码
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

// 分为奇数和偶数
val (oddNumbers, evenNumbers) = numbers.partition { it % 2 != 0 }
println(oddNumbers) // 输出:[1, 3, 5, 7, 9]
println(evenNumbers) // 输出:[2, 4, 6, 8, 10]

chunked - 分块

kotlin 复制代码
val numbers = (1..10).toList()

// 每三个元素分一组
val chunks = numbers.chunked(3)
println(chunks)
// 输出:[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]

// 分块并转换
val sumChunks = numbers.chunked(3) { chunk -> chunk.sum() }
println(sumChunks)
// 输出:[6, 15, 24, 10]

3.3.5 排序操作符

sorted - 排序

kotlin 复制代码
val numbers = listOf(5, 2, 8, 1, 9, 3)

// 升序排序
val ascNumbers = numbers.sorted()
println(ascNumbers) // 输出:[1, 2, 3, 5, 8, 9]

// 降序排序
val descNumbers = numbers.sortedDescending()
println(descNumbers) // 输出:[9, 8, 5, 3, 2, 1]

// 按条件排序
val users = listOf(
    User("1", "张三", "zhang@example.com", 25),
    User("2", "李四", "li@example.com", 30),
    User("3", "王五", "wang@example.com", 28)
)

val sortedByAge = users.sortedBy { it.age }
println(sortedByAge.map { it.name }) // 输出:[张三, 王五, 李四]

val sortedByAgeDesc = users.sortedByDescending { it.age }
println(sortedByAgeDesc.map { it.name }) // 输出:[李四, 王五, 张三]

3.3.6 集合转换操作符

flatMap - 扁平映射

kotlin 复制代码
val lists = listOf(
    listOf(1, 2, 3),
    listOf(4, 5, 6),
    listOf(7, 8, 9)
)

// 扁平化
val flattened = lists.flatMap { it }
println(flattened) // 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9]

// 扁平化并转换
val squares = lists.flatMap { list -> list.map { it * it } }
println(squares) // 输出:[1, 4, 9, 16, 25, 36, 49, 64, 81]

distinct - 去重

kotlin 复制代码
val numbers = listOf(1, 2, 2, 3, 3, 3, 4, 5, 5)

val distinctNumbers = numbers.distinct()
println(distinctNumbers) // 输出:[1, 2, 3, 4, 5]

// 按条件去重
val users = listOf(
    User("1", "张三", "zhang@example.com", 25),
    User("2", "张三", "zhang2@example.com", 30),
    User("3", "李四", "li@example.com", 25)
)

val distinctByName = users.distinctBy { it.name }
println(distinctByName.map { it.name }) // 输出:[张三, 李四]

3.3.7 序列(Sequence)与惰性求值

序列的优势:避免中间集合的创建,提高性能。

kotlin 复制代码
val numbers = (1..1000000).toList()

// 列表操作 - 创建多个中间集合
val result1 = numbers
    .filter { it % 2 == 0 } // 创建新集合
    .map { it * it } // 创建新集合
    .take(10) // 创建新集合

// 序列操作 - 不创建中间集合
val result2 = numbers
    .asSequence() // 转换为序列
    .filter { it % 2 == 0 } // 惰性求值
    .map { it * it } // 惰性求值
    .take(10) // 惰性求值
    .toList() // 终端操作,触发计算

序列 vs 列表性能对比

kotlin 复制代码
// 统计操作次数

    var operations = 0

    val result1 = (1..100)
        .filter { operations++; it % 2 == 0 }
        .map { operations++; it * it }
        .take(5)
        .toList()
    println("列表操作次数:$operations") // 输出:列表操作次数:150

    operations = 0
    val result2 = (1..100)
        .asSequence()
        .filter { operations++; it % 2 == 0 }
        .map { operations++; it * it }
        .take(5)
        .toList()
    println("序列操作次数:$operations") // 输出:序列操作次数:15

核心要点回顾

  1. Lambda 表达式

    • 函数式编程的核心思想
    • Lambda 语法与简化
    • 尾递归优化
    • 匿名函数与非局部返回
  2. 高阶函数与函数类型

    • 函数作为参数
    • 函数作为返回值
    • 闭包特性
    • 常用高阶函数(let, also, apply, with, run)
  3. 集合操作符

    • 基础操作符(map, filter)
    • 聚合操作符(reduce, fold, sum, average)
    • 查找操作符(find, first, last, any, all, none)
    • 分组操作符(groupBy, partition, chunked)
    • 排序操作符(sorted, sortedBy)
    • 序列与惰性求值
相关推荐
Eiceblue2 小时前
C# 实现 XLS 与 XLSX 格式双向互转(无需依赖 Office)
开发语言·c#·visual studio
我讲个笑话你可别哭啊2 小时前
Android Studio无线调试连接安卓设备
android·ide·android studio
pengyu2 小时前
【Kotlin 协程修仙录 · 炼气境 · 初阶】 | 感受天地灵气,写出第一个挂起函数
android·kotlin
林栩link2 小时前
Android CLI 与 Skills:提升 AI Coding 效率
android
水木流年追梦2 小时前
CodeTop Top 300 热门题目2-最长回文子串
开发语言·人工智能·python·算法·leetcode
良木生香2 小时前
【C++初阶】:STL——String从入门到应用完全指南(3)
c语言·开发语言·数据结构·c++·算法
fox_lht2 小时前
8.3.使用if let和let else实现简明的程序流控制
开发语言·后端·算法·rust
AI玫瑰助手3 小时前
Python基础:列表的定义、增删改查核心操作
android·开发语言·python
mOok ONSC3 小时前
对基因列表中批量的基因进行GO和KEGG注释
开发语言·数据库·golang