函数式编程范式主要依赖于高阶函数(以函数为参数或返回值)返回的数据,这些高阶函数专用于处理各种集合,可以联合使用多个同类函数构建链式操作以创建复杂的计算行为。kotlin支持多种编程范式,所以可以灵活运用面向对象编程和函数式编程来解决问题
一、变换
变换是函数式编程中的第一大类函数,变换函数会遍历集合内容,以一个值参传入的变换器函数,变换每个元素,返回包含已修改元素的集合给链上的其他函数
1.map
map变换函数会遍历接收者集合,让变换器函数作用于集合里的每个元素,返回修改后的集合,会作为链上下个函数的输入
代码语言:javascript复制fun main() {
val list = listOf("jack", "rose", "danny")
val mapList = list.map {
//将集合中每个元素首字母大写
it.capitalize()
}.map {
//将集合中每个元素加上i'm
"i'm $it"
}.apply(::println)//打印输出
}
结果: [i'm Jack, i'm Rose, i'm Danny]
原始集合并不会被修改,返回的是一个新的集合,函数式编程的设计理念就是不可变数据的副本在链上的函数间传递
map函数返回的集合大小和原集合一样,但类型不必相同
代码语言:javascript复制fun main() {
val list = listOf("jack", "rose", "danny")
val mapList = list.map {
//将集合中每个元素首字母大写
it.capitalize()
}.map {
//将集合中每个元素加上i'm后,计算字符串大小
"i'm $it".length
}.apply(::println)//打印输出
}
结果: [8, 8, 9]
2.flatMap
flatMap操作一个集合的集合,将多个集合合并成一个集合
代码语言:javascript复制fun main() {
val list = listOf("jack", "rose", "danny")
val list2 = listOf("jack1", "rose2", "danny3")
val bigList = listOf(list, list2)
val flat = bigList.flatMap {
it
}.apply(::println)
}
结果: [jack, rose, danny, jack1, rose2, danny3]
二、过滤
过滤是函数式编程中的第二大类函数,过滤函数接受一个predicate函数,用它按给定条件检查接收者集合中的每一个元素,并给出true或fasle,为true添加到新集合中
1.filter
代码语言:javascript复制fun main() {
val list = listOf("jack", "rose", "danny")
val filter = list.filter {
//过滤含有j的字符串
!it.contains("j")
}.apply(::println)
}
结果: [rose, danny]
组合使用,实现找素数
代码语言:javascript复制fun main() {
val list = listOf(7, 4, 8, 4, 3, 22, 18, 11)
//找素数
list.filter {number ->//过滤不是素数的元素
(2 until number).map {//遍历2到当前元素值
number % it //当前元素取余
}.none{it == 0}//为0则false
}.apply (::println)
}
结果: [7, 3, 11]
三、合并
合并是函数式编程中的第三大类函数,合并函数能将不同的集合合并成一个新集合,这和接收者是包含集合的集合的flatMap函数不同
1.zip
zip函数用来合并两个集合,返回一个包含键值对的新集合
代码语言:javascript复制fun main() {
val list = listOf("jack", "rose", "danny")
val list2 = listOf(14, 18, 23)
list.zip(list2).apply(::println)
}
结果: [(jack, 14), (rose, 18), (danny, 23)]
2.fold
fold函数用来合并值,这个函数接收一个初始累加器值,然后根据匿名函数的结果更新
代码语言:javascript复制fun main() {
val list = listOf(14, 18, 23)
list.fold(0) { acc, value ->
acc value
}.apply(::println)
}
结果: 55
四、为什么要使用函数式编程
五、序列
kotlin还有另外一类集合:惰性集合,类似于类的惰性初始化,惰性集合类型的性能表现优异,尤其是用于包含大量元素的集合时,因为集合元素是按需产生的 kotlin有个内置惰性集合类型叫序列,序列不会索引排序它的内容,也不记录元素个数,在使用一个序列时,它的元素可能有无限多,因为某个数据源能产生无限个元素
1.generateSequence
当你不知道要检查多少个元素才能得到想要的个数个元素时,可以使用generateSequence,如:获取从0开始的1000个素数
代码语言:javascript复制fun isPrime(number: Int): Boolean {
//过滤不是素数的元素
return (2 until number).map {
//遍历2到当前元素值
number % it //当前元素取余
}.none { it == 0 }//为0则false
}
fun main() {
//从3开始
val squence = generateSequence(3) { value ->
//每次加1
value 1
}.filter {
isPrime(it)
}.take(1000)
println(squence.toList().size)
}