一、集合操作相关高阶函数

Kotlin 集合框架提供了大量高阶函数,用于简化遍历、筛选、转换等操作,避免传统的 for 循环嵌套。

1. forEach:遍历集合元素

接收一个函数参数((T) -> Unit),对每个元素执行该函数。

val list = listOf(1, 2, 3)
list.forEach { println(it) }  // 遍历打印每个元素
// 等价于:for (item in list) { println(item) }
2. map:转换集合元素

接收一个函数参数((T) -> R),将集合中的每个元素通过该函数转换为新类型或者进行映射,返回新集合。

val numbers = listOf(1, 2, 3)
val squares = numbers.map { it * it }  // 转换为每个元素的平方:[1, 4, 9]

// 实际开发:将对象列表转换为属性列表
data class User(val id: Int, val name: String)
val users = listOf(User(1, "Tom"), User(2, "Jerry"))
val userNames = users.map { it.name }  // 提取所有用户名:["Tom", "Jerry"]
3. filter:筛选集合元素

接收一个函数参数((T) -> Boolean),保留函数返回 true 的元素,返回新集合。

val numbers = listOf(1, 2, 3, 4, 5)
val evenNumbers = numbers.filter { it % 2 == 0 }  // 筛选偶数:[2, 4]

// 筛选符合条件的对象
val adults = users.filter { it.age >= 18 }  // 保留成年用户
4. any / all / none:判断集合条件
  • any:判断是否至少有一个元素满足条件((T) -> Boolean)。
  • all:判断是否所有元素都满足条件。
  • none:判断是否所有元素都不满足条件(与 all { !condition } 等价)。
val numbers = listOf(1, 2, 3, 4)
numbers.any { it > 3 }  // true(存在>3的元素)
numbers.all { it < 5 }  // true(所有元素<5)
numbers.none { it < 0 } // true(没有元素<0)
5. fold / reduce:聚合计算
  • reduce:从第一个元素开始,通过函数((acc: T, T) -> T)累积计算结果(累加、累乘等)。
  • fold:与 reduce 类似,但可指定初始值(更灵活,支持不同类型的累积结果)。
val numbers = listOf(1, 2, 3, 4)
// 累加(reduce):1 + 2 → 3 + 3 → 6 + 4 → 10
numbers.reduce { acc, num -> acc + num }  // 结果:10

// 以初始值 10 累加(fold):10 + 1 + 2 + 3 + 4 = 20
numbers.fold(10) { acc, num -> acc + num }  // 结果:20

// 拼接字符串(fold 支持不同类型结果)
numbers.fold("Numbers: ") { acc, num -> acc + num + ", " }  // 结果:"Numbers: 1, 2, 3, 4, "
6. flatMap:扁平化集合

接收一个函数((T) -> Iterable<R>),先将每个元素转换为子集合,再将所有子集合合并为一个扁平集合。

data class Student(val name: String, val courses: List<String>)
val students = listOf(
    Student("Tom", listOf("Math", "English")),
    Student("Jerry", listOf("Physics", "Math"))
)

// 提取所有学生的课程(去嵌套)
val allCourses = students.flatMap { it.courses }  
// 结果:["Math", "English", "Physics", "Math"]

二、作用域函数(Scope Functions)

Kotlin 提供了 5 个作用域函数(letrunwithapplyalso),它们都是高阶函数,用于在对象的作用域内执行代码块,简化对象初始化、属性设置等操作。

1. let:对非空对象执行操作(常用)

接收函数((T) -> R),仅当对象非空时执行,参数用 it 指代对象,返回函数结果。

val str: String? = "hello"
// 非空时执行,避免手动判空
val length = str?.let { 
    println("字符串长度:${it.length}")  // it 指代 str
    it.length  // 返回长度
}
2. apply:对象配置(初始化)

接收函数(T.() -> Unit,扩展函数形式),参数用 this 指代对象,返回对象本身,适合设置多个属性。

// 配置 TextView
val textView = TextView(context).apply {
    text = "Hello"
    textSize = 16f
    setTextColor(Color.BLACK)
}
// apply 返回配置后的 textView 对象,可直接使用
3. run:综合操作(兼具 let 和 apply 特性)

有两种形式:

  • 作为对象的扩展函数:T.run { ... },类似 apply,但返回函数结果(而非对象本身)。
  • 独立调用:run { ... },用于执行一段代码块,返回最后一行结果。
// 扩展函数形式:处理对象并返回结果
val user = User(1, "Tom")
val userNameLength = user.run {
    name = "Tommy"  // this 指代 user
    name.length    // 返回名字长度
}

// 独立调用:执行代码块
val result = run {
    val a = 10
    val b = 20
    a + b  // 返回 30
}
4. with:对对象执行操作(类似 run 的非扩展形式)

接收一个对象和一个函数(T.() -> R),参数用 this 指代对象,返回函数结果(语法上是独立函数,非扩展函数)。

val user = User(1, "Tom")
val info = with(user) {
    "ID: $id, Name: $name"  // this 指代 user
}
5. also:附加操作(副作用)

接收函数((T) -> Unit),参数用 it 指代对象,返回对象本身,适合执行附加操作(如日志、打印)。

val list = mutableListOf(1, 2).also {
    println("原始列表:$it")  // 附加打印操作
}.apply {
    add(3)  // 继续添加元素
}
// 结果:list = [1, 2, 3],同时打印了原始列表

三、协程相关高阶函数

协程框架中的 launchasyncwithContext 等也是高阶函数,用于启动协程或切换线程。

1. launch:启动协程(无返回值)

接收函数(suspend CoroutineScope.() -> Unit),在协程作用域中执行代码,返回 Job 对象。

lifecycleScope.launch {  // launch 是高阶函数
    delay(1000)
    println("协程执行完毕")
}
2. async:启动协程(有返回值)

接收函数(suspend CoroutineScope.() -> T),返回 Deferred<T> 对象,通过 await() 获取结果。

viewModelScope.launch {
    val result = async { 
        fetchData()  // 异步获取数据
    }.await()  // 等待结果
}
3. withContext:切换协程调度器

接收调度器和函数(suspend CoroutineScope.() -> T),在指定调度器执行代码,返回结果。

suspend fun loadData() = withContext(Dispatchers.IO) {  // 切换到 IO 线程
    apiService.getData()  // 耗时操作
}

四、其他常用高阶函数

1. takeIf / takeUnless:条件过滤
  • takeIf:接收函数((T) -> Boolean),满足条件时返回对象本身,否则返回 null
  • takeUnless:与 takeIf 相反,不满足条件时返回对象本身。
val number = 10
// 满足条件(>5)时返回 10,否则返回 null
val validNumber = number.takeIf { it > 5 }  

// 不满足条件(>20)时返回 10,否则返回 null
val invalidNumber = number.takeUnless { it > 20 }
2. repeat:重复执行代码块

接收次数和函数((Int) -> Unit),重复执行函数 n 次,参数为当前索引(从 0 开始)。

repeat(3) { index ->  // 重复 3 次
    println("第 ${index + 1} 次执行")
}
Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐