ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 1. 前言 `Kotlin`官方提供了一些定义好的高阶函数,方便使用。`Kotlin`标准库定义了大量的对于集合操作的函数,在本节中我们将选取一些常用、具有代表性的函数进行讲解。 # 2. 查找 ![](https://img.kancloud.cn/a7/6e/a76e8e2be34b98326afe056ae237c197_966x519.png) 上图来源:[Kotlin从基础到实战-黑马程序员编著-微信读书 (qq.com)](https://weread.qq.com/web/reader/ab3320e0718ade85ab3fd1cka87322c014a87ff679a21ea) 用法其实都差不多这里仅做一个示范: ~~~ fun main() { var list = listOf<Int>(3, 4, 1, 3) println("列表中第一个大于3的元素:${list.find { it > 3 }}") } ~~~ 结果: ``` 列表中第一个大于3的元素:4 ``` 又比如: ~~~ fun main() { var list = listOf<Int>(3, 4, 1, 3, -3, -5, 0, 2, -1) println("列表中大于0的元素:${list.filter { it > 0 }}") } ~~~ 结果: ``` 列表中大于0的元素:[3, 4, 1, 3, 2] ``` 值得注意的是,方法声明为: ``` Iterable<T>.xxx ``` 我们可以进行仿写一个`find`方法: ~~~ fun <T> Iterable<T>.myFind(function: (a: T) -> Boolean): T? { for(ele in this){ if(function(ele)){ return ele } } return null } fun main() { var list = listOf(3, 4, 1, 3, -3, -5, 0, 2, -1) println("列表中第一个大于3的元素:${list.myFind { it > 3 }}") } ~~~ 结果: ``` 列表中第一个大于3的元素:4 ``` 这里的写法就比较类似于在`JavaScript`中的原型方法,只要定义在这个原型链上,就可以使用。至于其余的查找方法这里就不再一一给出案例。 # 3. 比较 ~~~ fun main() { var list = listOf(3, 4, 1, 3, -3, -5, 0, 2, -1) println(list.maxBy { it }) println(list.minBy { it }) println(list.distinctBy { it }) } ~~~ 结果: ``` 4 -5 [3, 4, 1, -3, -5, 0, 2, -1] ``` # 4. 标准库中的高阶函数 ![](https://img.kancloud.cn/a0/0f/a00f47566a55896d13c7123365ae3a83_958x658.png) ## 4.1 repeat ~~~ fun main() { repeat(3, { println("Hello world.") }) } ~~~ 结果: ``` Hello world. Hello world. Hello world. ``` ## 4.2 run ~~~ fun main() { var list = mutableListOf<Int>() run { list.add(2) list.add(3) } println(list) } ~~~ 结果: ``` [2, 3] ``` ## 4.3 其他常见标准函数 ### 4.3.1 apply ~~~ fun main() { var list = mutableListOf<Int>(3, 2, 4, 1) list = list.apply { //todo this为当前list } println(list) } ~~~ ### 4.3.2 let ~~~ fun main() { // 定义一个可以为空的字符串 var a: String? = "Hello" a = a?.let { // 如果不是空白字符串 if(it.isNotBlank()){ it.toUpperCase() } else{ "Hello" } } println(a) } ~~~ 结果: ``` HELLO ``` ### 4.3.3 let ~~~ fun main() { var session: String? = null var msg = session?.let { "Welcome!" } ?: "Not login yet." println(msg) } ~~~ 结果: ``` Not login yet. ``` ### 4.3.4 run ~~~ fun main() { var session: String? = "Message" var msg = session?.run { contains("M") } println(msg) } ~~~ 结果 ``` true ``` ### 4.3.5 also 在前面的案例中,我们可以使用`run`或者`apply`来进行应用一些操作。但是,有些时候,我们需要在同一原始对象上做不同的操作,就可以使用`also`来实现。比如下面的案例: ~~~ fun main() { var username = "danjffkdfjk" username?.also { it.run(::process) .run(::isToLong) .run(::getMessage) .run(::println) }.also { println("原始字符串内容为:${it}") } } ~~~ 结果: ``` 用户名过长! 原始字符串内容为:danjffkdfjk ``` ### 4.3.6 takeIf 类似于`if`,但是可以直接作用于对象上,比较方便。当判断`lambda`表达式为`true`返回接受者对象,否者返回`null`。比如下面的案例: ~~~ fun main() { var file: File? = File("./Coding/src/main/java/com/kotlinLearn/a.txt") // 使用takeIf来判断一下文件是否可读 var content = file?.takeIf { it.canRead() } ?.readText() println(content) } ~~~ 结果输出文件内容。 对于这个功能,其最终会转换为: ``` File var10000 = file.canRead() ? file : null; ``` 不妨在`IDEA`中使用`SHIFT`进行搜索`show kotlin ByteCode`,然后点击`Decompile`可以看到生成的代码: ![](https://img.kancloud.cn/eb/61/eb61e95705e418007f4035268db65681_368x126.png) ### 4.3.7 综合案例 ~~~ fun isToLong(string: String):Boolean{ return string.length > 5 } fun main() { var username = "danjffkdfjk" username?.let { if(it.isNotBlank()) { it.toUpperCase() } else{ "Empty!" } }.run(::isToLong).apply { if(this){ println("用户名过长!") } else{ println("用户名满足条件") } } } ~~~ 结果: ``` 用户名过长! ``` 当然,我们可以让代码更加规范: ~~~ fun process(string: String): String { if (string.isNotBlank()) { return string.toUpperCase() } return "Empty!" } fun isToLong(string: String): Boolean { return string.length > 5 } fun getMessage(boolean: Boolean): String { if (boolean) { return "用户名过长!" } return "用户名满足条件" } fun main() { var username = "danjffkdfjk" username?.run(::process) .run(::isToLong) .run(::getMessage) .run(::println) } ~~~ 结果是一样的,只是这里将功能抽离为了方法。然后使用`::`来进行引用。