《Kotlin高阶函数完全指南:从入门到精通的15个核心函数》
引言
Kotlin 的高阶函数是其最强大的特性之一,它让代码更简洁、更具表现力。本文将基于实际代码示例,全面介绍 Kotlin 中的作用域函数、集合操作函数、延迟执行函数、判断检查函数以及内联函数,帮助你彻底掌握这些核心概念。
作用域函数
let --- 空安全调用利器
let 在对象上下文中执行代码块,返回最后一行的结果,最常用于空安全调用。
kotlin
/**
* let:在对象上下文中执行代码块,返回最后一行结果,常用于空安全调用
*/
fun letDemo() {
val name = "Kotlin"
val length = name.let {
Log.d("MainActivity2", it)
it.length
}
Log.d("MainActivity2", "$length")
}
/**
* let + 安全调用:仅在 user 不为 null 时执行
*/
fun letDemo1(user: User?) {
user?.let {
Log.d("MainActivity2", "name:${it.name}")
Log.d("MainActivity2", "age:${it.age}")
}
}
run --- 使用 this 作为上下文
run 与 let 类似,但使用 this 作为上下文引用,同样返回最后一行结果。
kotlin
/**
* run:类似 let,但直接使用 this 作为上下文,返回最后一行结果
*/
fun runDemo(user: User?) {
val finalStr = user?.run {
val finalData = "name:${user.name} age:${user.age}"
finalData
}
Log.d("MainActivity2", "finalStr:$finalStr")
}
with --- 非扩展函数形式
with 不是扩展函数,需要将对象作为参数传入,适用于对同一对象进行多次操作。
kotlin
/**
* with:非扩展函数,传入对象作为上下文,返回最后一行结果
*/
fun withDemo(name: String, age: Int): String {
return with(StringBuilder()) {
append("姓名:")
append(name)
append(" ")
append("年龄:")
append(age)
append("岁")
toString()
}
}
apply --- 对象初始化神器
apply 返回对象本身,非常适合用于初始化对象属性。
kotlin
/**
* apply:返回对象本身,常用于初始化对象属性
*/
fun applyDemo(): User {
return User().apply {
name = "Kotlin-Apply"
age = 15
}
}
also --- 附加操作的好帮手
also 同样返回对象本身,常用于日志记录、调试等附加操作。
kotlin
/**
* also:返回对象本身,常用于附加操作如日志记录
*/
fun alsoDemo() {
val result = User()
.also { Log.d("MainActivity2", "开始记录") }
.apply { name = "Kotlin-Also" }
.also { Log.d("MainActivity2", "name:${it.name}") }
.apply { age = 15 }
.also { Log.d("MainActivity2", "age:${it.age}") }
Log.d("MainActivity2", "最终的结果:$result")
}
集合操作函数
map --- 元素类型转换
将集合中的每个元素转换为另一种类型。
kotlin
/**
* map:将集合中的每个元素转换为另一种类型
*/
fun mapDemo(): List<Info> {
val dataList = mutableListOf<User>()
val user1 = User().apply {
name = "Kotlin"
age = 15
}
dataList.add(user1)
val user2 = User().apply {
name = "Android"
age = 16
}
dataList.add(user2)
val mapList = dataList.map { data ->
Info().apply {
name = data.name
age = data.age
}
}
return mapList
}
filterNotNull --- 过滤空值
kotlin
/**
* filterNotNull:过滤掉集合中的 null 元素
*/
fun filterDemo(): List<User> {
val listData = listOf(User().apply {
name = "这是一个user"
age = 10
}, null)
val finalData = listData.filterNotNull()
return finalData
}
forEach --- 遍历集合
kotlin
/**
* forEach:遍历集合并执行操作
*/
fun forEachDemo() {
val listData = listOf(1, 2, 3, 4, 5)
listData.forEach {
Log.d("MainActivity2", "$it")
}
}
reduce --- 累积计算
kotlin
/**
* reduce:从第一个元素开始累积计算
*/
fun reduceDemo(): Int {
// reduce: 从第一个元素开始累积
val numbers = listOf(1, 2, 3, 4, 5)
val finalData = numbers.reduce { acc, n -> acc + n }
return finalData
}
groupBy --- 分组
kotlin
/**
* groupBy:按条件分组,返回 Map
*/
fun groupByDemo(): List<Int>? {
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 按奇偶分组
val groupedByParity = numbers.groupBy { if (it % 2 == 0) "偶数" else "奇数" }
val finalData = groupedByParity["偶数"]
return finalData
}
sortedBy --- 排序
kotlin
/**
* sortedBy:按指定规则排序
*/
fun sortedByDemo(): List<String> {
val words = listOf("Kotlin", "Java", "Python", "Go", "Rust")
val byLength = words.sortedBy { it.length }
return byLength
}
延迟执行函数
lazy --- 懒加载
lazy 委托属性只在首次访问时才创建对象,常用于耗时的初始化操作。
kotlin
/**
* lazy:延迟初始化,首次访问时才创建对象
*/
fun lazyDemo(): User {
val userInfo by lazy { User() }
return userInfo
}
repeat --- 重复执行
kotlin
/**
* repeat:重复执行某段代码 n 次
*/
fun repeatDemo() {
repeat(20) {
Log.d("MainActivity2", "Hello Kotlin")
}
}
判断/检查函数
any
是否存在至少一个满足条件
kotlin
/**
* any:是否存在至少一个元素满足条件
*/
fun anyDemo(): Boolean {
val numbers = listOf(1, 2, 3, 4, 5)
val hasEven = numbers.any { it % 2 == 0 }
return hasEven
}
all
是否所有元素都满足条件
kotlin
/**
* all:是否所有元素都满足条件
*/
fun allDemo(): Boolean {
val numbers = listOf(2, 4, 6, 8, 10)
val allEven = numbers.all { it % 2 == 0 }
return allEven
}
none
是否没有元素满足条件
kotlin
/**
* none:是否没有元素满足条件
*/
fun noneDemo(): Boolean {
val numbers = listOf(1, 2, 3, 4, 5)
val noEven = numbers.none { it % 2 == 0 }
return noEven
}
count
统计满足条件的元素个数
kotlin
/**
* count:统计满足条件的元素个数
*/
fun countDemo(): Int {
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val evenCount = numbers.count { it % 2 == 0 }
return evenCount
}
firstOrNull
查找第一个满足条件的元素
kotlin
/** firstOrNull:查找第一个满足条件的元素,找不到返回 null */
fun findDemo(): Int? {
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val sameAsFirstOrNull = numbers.firstOrNull { it % 2 == 0 }
return sameAsFirstOrNull
}
内联函数 inline(核心重点)
Lambda 的本质问题
普通的高阶函数在运行时,每次调用都会创建一个匿名函数对象(Lambda 对象),带来额外的内存开销和性能损耗。
kotlin
// 普通高阶函数
fun operateOnNumber(x: Int, operation: (Int) -> Int): Int {
return operation(x)
}
编译后近似等价于:
kotlin
val lambda = object : Function1<Int, Int> {
override fun invoke(x: Int): Int = x * 2
}
val result = operateOnNumber(5, lambda) // 每次调用都创建对象
inline 解决方案
使用 inline 关键字,编译器会将函数体直接"内联"到调用处,消除 Lambda 对象的创建
kotlin
inline fun operateOnNumber1(x: Int, operation: (Int) -> Int): Int {
return operation(x)
}
fun inlineDemo() {
val result = operateOnNumber1(5) { it * 2 }
// 编译后代码会被内联为:val result = 5 * 2
}
inline 的两大好处
消除 Lambda 对象创建 --- 减少内存分配和 GC 压力
支持非局部返回 --- 可以在 Lambda 中直接 return 外层函数
注意:inline 虽好,但不宜滥用。对于较大的函数体,内联会导致字节码膨胀,此时可考虑使用 noinline 或 crossinline。
掌握这些高阶函数,能让你的 Kotlin 代码更加简洁、优雅、高效。建议在实际开发中有意识地使用这些函数,逐步形成函数式编程思维。