内容简介
说实话,当我在次看见高阶函数的时候,我都纳闷了?啥是高阶函数呢?网上查了查好像没有特别的定义。网上有人定义为 将函数当做参数或者返回值的函数,好吧。。。就这么认为吧。回想下前面讲的 作用域函数 好像也是高阶函数哦。
常用的高阶函数
试想下,这样函数的超级多,定义也相当简单。因为 kotlin
是支持函数可以变成参数的形式传递(想想前面讲的函数为何能传递呢?友情提醒 FunctionN
对象)。
Kotlin
为我们提供了很多高阶函数,一般都是以扩展函数的形式去定义的。当然我们也可以自己定义高阶函数,这里就说下我知道的几个吧,这样的函数太多了,大家自己去看看源码。
友情提醒:个人认为,自己定义的高阶函数若经常使用,可以使用
inline
(内联函数)修饰,减少不必要的对象创建开销。
forEach
遍历每个元素,源码太简单啦,自行脑补吧!!
fun main() {
val arrays = arrayOf(1, 2, 3, 4)
/**
* 遍历每个元素
*/
arrays.forEach {
}
}
map
和 RxJava
的一样,对每个数据进行转换,并返回新的数据集合。 kotlin
天生支持函数式编程的哦(原理就是牛X的扩展方法)。
fun main() {
val arrays = arrayOf("1", "2", "3", "4")
/**
* 遍历每个元素
*/
val map = arrays.map {
it.toInt()
}
/**
* 遍历
*/
map.forEach(::println)
}
floatMap
和 RxJava
有点不同,遍历集合每个元素,每个元素调用一次 Lambda
表达式且返回一个集合,最终整合在一个集合中返回。
fun main() {
val arrays = arrayOf("1,2,3", "2,3,4", "3,2", "4,3")
val flatMap = arrays.flatMap {
it.split(",").map { it.toInt() }
}
/**
* 遍历
*/
flatMap.forEach(::println)
}
fold
给定一个一个初始值,传入 Lambda
表达式第一个参数就是上次元素返回的结果,大家看看源码吧,这个不是很好解释。
我这个功能就是做了一个字符串数组求和。
fun main() {
val arrays = arrayOf("1", "2", "3", "4")
val fold = arrays.fold(0) { acc, s ->
acc + s.toInt()
}
println(fold)
}
sumBy
其实上面我通过 fold
做了一个字符串数组求和的实例,不过使用 sumBy
更为的适合这个例子。就是遍历其每个元素,传入的 Lambda
表达返回一个 Int
并求和(看源吗吧,瞜一眼便知)。
fun main() {
val arrays = arrayOf("1", "2", "3", "4")
arrays.sumBy {
it.toInt()
}.let(::println)
}
reduce
这个和上面的 fold
类似,但是无需传入初始值了,初始值变成了数组的第一个元素(注意这个遍历就跳过了第一个元素哦)
/**
* 继续求和
*/
fun main() {
val arrays = arrayOf(1, 2, 3, 4)
val reduce = arrays.reduce { acc, s ->
acc + s
}
println(reduce)
}
filter
过滤元素,只有 Lambda
表达式返回 ture
,才会加入返回集合当中。
fun main() {
val arrays = arrayOf(1, 2, 3, 4)
val filter = arrays.filter {
it % 2 == 0
}
filter.forEach(::println)
}
all
集合中,所有元素满足 Lambda
条件,返回 ture
,否则返回 false
fun main() {
val arrays = arrayOf(1, 2, 3, 4)
val all = arrays.all {
it > 2
}
println(all)
}
any
集合中,有任意一个元素,满足 Lambda
条件返回 true
fun main() {
val arrays = arrayOf(1, 2, 3, 4)
val all = arrays.all {
it > 2
}
println(all)
}
count
满足 Lambda
表达式条件的元素个数。
fun main() {
val arrays = arrayOf(1, 2, 3, 4)
val all = arrays.count {
it > 2
}
println(all)
}
find & findLast
find
是在集合中查找第一个 Lambda
返回 true
的元素,并返回。而 findLast
是在集合中查找最后一个 Lambda
返回 true
的元素。
查找不到返回 null
fun main() {
val arrays = arrayOf(1, 2, 3, 4)
val find = arrays.find {
it > 2
}
println(find)
val findLast = arrays.findLast {
it > 2
}
println(findLast)
}
first & firstOrNull
集合中查找第一个 Lambda
返回 true
的元素,唯一区别就是 first
没有查找到会抛出异常, firstOrNull
会返回 null
( firstOrNull
和 find
是等价的)。
fun main() {
val arrays = arrayOf(1, 2, 3, 4)
/**
* 查找第一个元素大于 2 的元素,若没有抛出 NoSuchElementException 异常
*/
val find = arrays.first {
it > 2
}
/**
* 查找第一个元素大于 2 的元素,若没有返回 null
*/
val find2 = arrays.firstOrNull() {
it > 2
}
}
use
use
主要是对 Stream
的扩展, java
的读写文件相当费劲,尤其是复杂关流的操作,想想简直就是噩梦。有了 use
操作符就不需要关系那么多啦!
fun main() {
/**
* use 内部对流的关闭,做了处理,我们无需关系流是否关闭没
*/
FileInputStream("build.gradle").use {
String(it.readBytes())
}.let(::println)
}
总结
实在太多了,大家边遇到边学习吧。其实原理都很简单,就是扩展封装罢了。最终要的就是,明白前面讲的函数为何能当参数传递。
这篇重在实践,高阶函数为我们开发带来了很多便利、大家多多去挖掘好用的高阶函数吧。
我个人认为这些函数能将很多复杂的业务变成链式写法。