与普通函数不一样,高阶函数是传入或者返回函数的函数,例如,我们可能用到的forEach就是一个高阶函数
示例代码:
fun main() {
val myOperate = AdvanceOperate() //定义实例
val operate1 = myOperate.multipleOperate(2,3){ //高阶函数调用
num1, num2 -> "plus operate:$num1 + $num2 = ${num1+num2}"
}
println(operate1)
val operate2 = myOperate.multipleOperate(2,3){
num1, num2 ->
"chengfa operate:$num1 * $num2 = ${num1*num2}" //定义成两个数的积
}
println(operate2)
}
class AdvanceOperate{
//定义高阶函数
fun multipleOperate(num1:Int,num2:Int,operate:(num1:Int,num2:Int)->String):String{//第三个参数为普通函数
println("$num1 and $num2 for different operate")
return operate(num1,num2)
}
}
运行结果:
2 and 3 for different operate
plus operate:2 + 3 = 5
2 and 3 for different operate
chengfa operate:2 * 3 = 6
map/flatMap
val strs:Array = arrayOf("Hello","USA","England","China") //定义一个字符串数组
strs.forEach (::println) //通过forEach打印(这里forEach也是一个高阶函数,println是包级函数)
println("-----------------------")
val newStrs = strs.map { "$it length is ${it.length}" } //通过高阶函数map映射功能生成一个新list
newStrs.forEach(::println)
运行打印结果:
Hello
USA
England
China
-----------------------
Hello length is 5
USA length is 3
England length is 7
China length is 5
map源码:
/**
* Returns a list containing the results of applying the given [transform] function
* to each element in the original array.
*/
public inline fun Array.map(transform: (T) -> R): List {
return mapTo(ArrayList(size), transform)
}
源码解读:
描述:可以看出他是Array的一个扩展函数,返回一个通过[transform]函数对原始数组中的元素进行一一映射后生成的新list
参数transform是一个参数为T并返回R的函数
返回值类型是List
另外,可以看下forEach的源码:
/**
* Performs the given [action] on each element.
*/
public inline fun Array.forEach(action: (T) -> Unit): Unit {
for (element in this) action(element) //通过for循环对Array里的元素以action方法进行处理
}
源码解读:
forEach函数也是Array中的一个扩展函数,而action可以为任意同以element为参数的函数
flat:n 平面,面,片,住宅,套件;adj 平坦的,平的,扁
示例代码
val list = listOf(
1..3,
2..5,
1..6,
)
val flatList = list.flatMap { it }
flatList.forEach{
print("$it,")
}
运行结果:
1,2,3,2,3,4,5,1,2,3,4,5,6,
flatMap源码解读
/**
* Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original collection.
*/
public inline fun Iterable.flatMap(transform: (T) -> Iterable): List {
return flatMapTo(ArrayList(), transform)
}
//可以看到,与map不一样的是flatMap的作为参数的函数[transform]返回的不是单纯的数据R而是一个R的集合[Iterable],而flatMap本身的返回值同map一样是一个List
//再看flatMapTo方法:
/**
* Appends all elements yielded from results of [transform] function being invoked on each element of original collection, to the given [destination].
*/
public inline fun > Iterable.flatMapTo(destination: C, transform: (T) -> Iterable): C {
for (element in this) { //这里通过for循环以及下面我们熟悉的addAll方法可以知道原始数组的数据就这样添加到了新的List中
val list = transform(element)
destination.addAll(list)
}
return destination
}
当然,我们也可以对进行稍微复杂的操作,比如对最终返回List的元素进行乘方在添加“Num.”
val flatList2 = list.flatMap { intRange ->
intRange.map { //注意,这里要区分intRange和it,从上面的源码我们知道IntRange是一个数组,所以需要用map方法映射元素最终形式
"Num.${it*it}"
}
}
flatList2.forEach{
print("$it ")
}
运行结果:
Num.1 Num.4 Num.9 Num.4 Num.9 Num.16 Num.25 Num.1 Num.4 Num.9 Num.16 Num.25 Num.36
fold/reduce
reduce:vi 减少,降低,缩小,压缩,简化,裁剪
def:make smaller or less in account,degree,or size
reduce方法源码:
/**
* Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element.
* 从第一个元素开始累积值,并从左到右应用[operation]到当前累加器值和每个元素。(谷歌翻译)
*/
public inline fun Iterable.reduce(operation: (acc: S, T) -> S): S {
val iterator = this.iterator()
if (!iterator.hasNext()) throw UnsupportedOperationException("Empty collection can't be reduced.")
var accumulator: S = iterator.next()
while (iterator.hasNext()) {
accumulator = operation(accumulator, iterator.next()) //累计过程,通过operation方法,计算相关结果
}
return accumulator
}
由上可知,我们可以用该方法实现一个累加、累乘等功能,比如,实现一个数列的累加,累乘:
val sum_he = flatList.reduce { acc, num -> acc + num }
println("sum = $sum_he")
println("-----------------------")
val sum_ji = flatList.reduce { acc, num -> acc * num }
println("sum = $sum_ji")
运行结果:
sum = 41
----------------------
sum = 518400
fold:vi 折,折叠,合拢,抱住;n 合拢,圈
fold方法源码:
/**
* Accumulates(累计,累加) value starting with [initial] value and applying [operation] from left to right to current accumulator value and each element.
* 累计以[initial]值开始并从左到右应用[operation]到当前累加器值和每个元素的值。(谷歌翻译)
*/
public inline fun Iterable.fold(initial: R, operation: (acc: R, T) -> R): R {
var accumulator = initial
for (element in this) accumulator = operation(accumulator, element)
return accumulator
}
通过源码可知,fold与reduce方法功能基本一致,唯一不一样的地方是fold多了一个指定初始值参数[initial],而reduce方法是没有这个参数的,同样可以通过示例代码理解fold方法:
val sum = flatList.fold(10){
acc, i -> acc+i
}
println("sum = $sum")
运行结果:
sum = 51
filter/takeWhile
filter:vi 过滤,筛选;adj 过滤器,滤波器
filter方法源码:
/**
* Returns a list containing only elements matching the given [predicate].
* 返回仅包含与给定[predicate]匹配的元素的列表。(谷歌翻译)
*/
public inline fun Iterable.filter(predicate: (T) -> Boolean): List {
return filterTo(ArrayList(), predicate)
}
很明显这是一个过滤器方法,通过[predicate]方法过滤掉不符合规则的元素,返回一个新的list
由此,我们可以编写示例方法,比如,我们要筛选出列表中的偶数
val evenList = flatList.filter {
it%2 == 0
}
evenList.forEach{print("$it,")}
运行结果
2,2,4,2,4,6,
takeWhile:v 拿走
takeWhile方法源码:
/**
* Returns a list containing first elements satisfying the given [predicate].
* 返回包含满足给定方法[predicate]的第一个元素的列表。(谷歌翻译)
* @sample samples.collections.Collections.Transformations.take
*/
public inline fun Iterable.takeWhile(predicate: (T) -> Boolean): List {
val list = ArrayList()
for (item in this) {
if (!predicate(item))
break
list.add(item)
}
return list
}
很明显,它返回的是一个元素满足[predicate]方法的list,循环获取集合中的元素,一旦发现某个元素不符合该规则,程序立马跳出循环,返回一个新list
写一个item != 5 的方法调用。ps:不知道该方法有何可用之地
val takeWhile = flatList.takeWhile {
it != 5
}
takeWhile.forEach{print("$it,")}
运行结果:
1,2,3,2,3,4,
let/apply/with/use
这几个函数都是为了简洁化代码而设计的,篇幅原因,这里不做详解(懒!!!)