Kotlin之集合的函数式API(Lambda)

集合的函数式 API 有很多种,我们只重点学习函数式 API 的结构,也就是 Lambda 表达式的语法结构

要求:在集合中找出名字最长的那个值:

fun main() {
    val list = listOf("a", "ab", "abc", "bc")
    var maxLength = ""
    for (name in list) {
        if (name.length > maxLength.length) {
            maxLength = name
        }
    }
    print("max is $maxLength")
}

以上虽然说是一段很清晰的代码,但是如果使用函数式编程,可以变的更加简单:

fun main() {
    val list = listOf("a", "ab", "abc", "bc")
    val maxLength = list.maxBy { it.length }
    print("max is $maxLength")
}

以上就是函数式 API 的用法,只用一行代码就可以找到最长的名字,现在看可能还会摸不着头脑,那是因为我们还没有学习 Lambda 表达式的语法结构,那就上 Lambda 的语法结构

Lambda 的定义

Lambda 是一小段可以作为参数传递的代码

一般来说,我们向某个函数传参时只能传入变量,而借助 Lambda 却可以传入一小段代码,那么多长才算一小段代码呢?Kotlin 没有对此进行限制,但通常不建议在 Lambda 中写太长的代码,否则可能会影响代码的可读性

Lambda 语法结构

{ 参数名1: 参数类型, 参数名2: 参数类型 -> 函数体 }

首先最外层是一个大括号,如果有数据传入到 Lambda 表达式当中的话,我们还需要声明参数列表,参数列表的结尾使用的是 -> 符号,表示参数列表的结束以及函数体的开始,并且最后一行会自动作为 Lambda 的返回值

在很多情况下,我们不需要使用 Lambda 的完整的语法结构,而是有很多种简化的写法,但是简化版的似乎更难理解,我们一步步推倒简化版的由来,从而理解 Lambda 表达式的语法结构

回到刚才寻找最长单词的要求,前面使用的函数式 API 的语法结构看上去好像很特殊,但其实 maxBy 就是一个普通的函数而已,只不过他接收的是一个 Lambda 类型的参数,并且在遍历集合的时候将每次遍历的值作为参数传给 Lambda 表达式. maxBy 函数的工作原理是根据我们传入的条件来遍历集合,从而找到该条件下的最大值,所以说刚好符合我们查找最大长度的单词的需求

现在来演示一下推倒过程

根据以上的工作原理可得:

fun main() {
    val list = listOf("a", "ab", "abc", "bc")
    val lambda = { name: String -> name.length }
    val maxLength = list.maxBy(lambda)
    print("max is $maxLength")
}

可以看到 maxBy 函数实质上就是接收了一个 Lambda 函数而已,并且这个 Lambda 函数完全可以按照刚刚说的表达式的语法结构来定义

这种写法虽然可以工作,但是比较啰嗦,可简化的点也很多

首先,我们不需要专门定义一个lambda变量,而是可以将lambda表达式直接传入函数当中:

val maxLength = list.maxBy({ name: String -> name.length })

Kotlin规定,当Lambda参数是函数的最后一个参数时,可以将 Lambda 表达式移动到函数的括号外面:

val maxLength = list.maxBy() { name: String -> name.length }

如果 Lambda 参数是函数唯一的参数的话,还可以将函数的括号省略:

val maxLength = list.maxBy { name: String -> name.length }

由于 Kotlin 拥有出色的类型推到极致, Lambda 表达式中的参数在大多数情况下不必声明参数类型:

val maxLength = list.maxBy { name -> name.length }

当 Lambda 表达式的参数列表中只有阳光参数时,也不用声明参数名,可以使用 it 关键字来代替:

val maxLength = list.maxBy { it.length }

这就是最初的我们的那种写法

几个集合中比较常用的函数式 API

map

集合中的 map 函数是最常用的一种函数式 API ,他用于将集合中的每个元素都映射成一个另外的值,映射的规则在 Lambda 表达式中指定,最终生成一个新的集合. 比如我们把所有的名称都变成大写:

fun main() {
    val list = listOf("a", "ab", "abc", "bc")
    val maxLength = list.map { it.toUpperCase() }
    for (name in maxLength) {
        println(name)
    }
}

map 的功能非常强大,他可以按照我们的需求对集合中的元素进行任意的映射转换,只需要在 Lambda 中编写你需要的逻辑即可

filter

filter 函数是用来过滤集合中的数据都,他可以单独使用,也可以配合刚才的 map 函数一起使用

比如我们只保留两个字母以内的,就可以借助 filter 来实现

fun main() {
    val list = listOf("a", "ab", "abc", "bc")
    val maxLength = list.filter { it.length < 3 }.map { it.toUpperCase() }
    for (name in maxLength) {
        println(name)
    }
}

需要注意调用顺序来提高效率

any和all

any 用于判断集合中是否至少存在一个元素满足指定条件

all 用于判断集合中是否所有的元素都满足指定条件

fun main() {
    val list = listOf("a", "ab", "abc", "bc")
    val anyResult = list.any { it.length <= 3 }
    val allResult = list.all { it.length <= 3 }

    println("anyResult is $anyResult, allResult is $allResult")
}

微信扫描二维码,关注我的公众号
欢迎关注这个不是技术号的公众号,我们聊聊别的。

你可能感兴趣的:(Kotlin,Lambda,android,kotlin)