第17章 Kotlin中函数式编程API
为了提供对函数式编程的支持,Kotlin在集合和数组中提供了一些高阶函数,它们的参数和返回类型都是函数类型。因为集合和数组它们都是数据的容器,即按照某种算法实现的数据结构,这些数据在这些函数中“流动”最后输出结果。集合和数组中的这些高阶函数构成了Kotlin函数式编程API,本章介绍这些API。
17.1 函数式编程API与链式调用
函数操控的是数据,数据是放在集合或数组中的,而集合和数组在数学中计算可以分为:遍历、排序、过滤、映射、聚合等等。因此凡是支持函数式编程的语言,它们的函数式编程API都是类似的,如forEach、sort、map、filter、max和count等函数,这些函数在所有函数式编程语言中都是一样的,而且大部函数的命名也是完全一样,只要你熟悉了一个函数的使用,无论换成什么语言用法也是一样的,很容易学习。
函数式编程将用户需求和业务逻辑被抽象成为函数,通过函数的不同组合调用完成复杂的业务逻辑。下面的代码片段是采用函数式编程的链式调用风格实现。
fun getUsers(db: ManagedSQLiteOpenHelper):
List = db.use {
db.select(“Users”)
.whereSimple(“family_name = ?”, “John”)
.doExec()
.parseList(UserParser)
}
getUsers函数中db.select(“Users”).whereSimple(“family_name
= ?”, “John”).doExec().parseList(UserParser)是一条语句,实现了从Users表中查询family_name = John的数据。它就是通过多个函数的组合而实现的,这种多个函数组合就是链式调用,这种链式调用风格如图17-1所示,关注输入和输出,输入数据(通常是集合或数组)通过多个函数的连续计算输出数据(通常也是集合或数组),不修改函数之外的变量,是无状态的。
17.2 遍历操作
对数据的操作主要是遍历、过滤、映射和聚合,其中遍历在前面第16章介绍已经介绍过了,但采用方式还是传统的for循环。而函数式编程遍历数据应该使用forEach和forEachIndexed函数。
17.2.1 forEach
forEach函数适用于Collection和Map集合,以及数组,函数只有一个函数类型的参数,实参往往使用尾随形式的Lambda表达式。在执行时forEach会把集合或数组中的每一个元素传递给Lambda表达式(或其他的函数引用)以便去执行。
示例代码如下:
//代码文件:chapter17/src/com/a51work6/section2/ch17.2.1.kt
package com.a51work6.section2
fun main(args: Array) {
val strArray =arrayOf("张三","李四", "王五","董六") //创建字符串数组
val set =setOf(1, 3, 34, 54, 75) //创建Set集合
val map =mapOf(102 to "张三", 105 to "李四", 109 to "王五") //创建Map集合
println(“—–遍历数组—–“)
strArray.forEach {
println(it)
}
println(“—–遍历Set集合—–“)
set.forEach {
println(it)
}
println(“—–遍历Map集合k,v—–“)
map.forEach {k, v -> ①
println(“$k –
KaTeX parse error: Expected ‘EOF’, got ‘}’ at position 9: v”) }̲ println…
{it.key} – ${it.value}”)
}
}
输出结果:
—–遍历Set集合—–
1
3
34
54
75
—–遍历Map集合k,v—–
102 – 张三
105 – 李四
109 – 王五
—–遍历Map集合Entry—–
102 – 张三
105 – 李四
109 – 王五
上述代码数组和Set集合的forEach函数的Lambda表达式都只有一个参数,而遍历Map集合时分为两个版本,其中代码第①行的forEach函数的Lambda表达式中有两个参数,第一个参数是集合的键,第二个参数是集合的值。代码第②行的forEach函数的Lambda表达式中有一个参数,这个参数类型是Entry,Entry表示一个键值对的对象,它有两个属性,即key和value。
17.2.2 forEachIndexed
使用forEach函数无法返回元素的索引,如果既想返回集合元素,又想返回集合元素索引,则可以使用forEachIndexed函数,forEachIndexed适用于Collection集合和数组。
示例代码如下:
//代码文件:chapter17/src/com/a51work6/section2/ch17.2.2.kt
package com.a51work6.section2
fun main(args: Array) {