函数式编程范式主要依赖于高阶函数(以函数为参数或返回值)返回的数据,这些高阶函数专用于处理各种集合,可以联合使用多个同类函数构建链式操作以创建复杂的计算行为。kotlin支持多种编程范式,所以可以灵活运用面向对象编程和函数式编程来解决问题
一、变换
变换是函数式编程中的第一大类函数,变换函数会遍历集合内容,以一个值参传入的变换器函数,变换每个元素,返回包含已修改元素的集合给链上的其他函数
1.map
map变换函数会遍历接收者集合,让变换器函数作用于集合里的每个元素,返回修改后的集合,会作为链上下个函数的输入
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函数返回的集合大小和原集合一样,但类型不必相同
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操作一个集合的集合,将多个集合合并成一个集合
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
fun main() {val list = listOf("jack", "rose", "danny")val filter = list.filter {//过滤含有j的字符串!it.contains("j")}.apply(::println)
}
结果:
[rose, danny]
组合使用,实现找素数
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函数用来合并两个集合,返回一个包含键值对的新集合
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函数用来合并值,这个函数接收一个初始累加器值,然后根据匿名函数的结果更新
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个素数
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 ->//每次加1value + 1}.filter {isPrime(it)}.take(1000)println(squence.toList().size)
}