kotlin学习之高阶函数及常用基本高阶函数
Posted mictoy_朱
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kotlin学习之高阶函数及常用基本高阶函数相关的知识,希望对你有一定的参考价值。
基本概念 f(g(x))
与普通函数不一样,高阶函数是传入或者返回函数的函数,例如,我们可能用到的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
- map:数组映射
val strs:Array<String> = 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 <T, R> Array<out T>.map(transform: (T) -> R): List<R>
return mapTo(ArrayList<R>(size), transform)
源码解读:
描述:可以看出他是Array的一个扩展函数,返回一个通过[transform]函数对原始数组中的元素进行一一映射后生成的新list
参数transform是一个参数为T并返回R的函数
返回值类型是List
另外,可以看下forEach的源码:
/**
* Performs the given [action] on each element.
*/
public inline fun <T> Array<out T>.forEach(action: (T) -> Unit): Unit
for (element in this) action(element) //通过for循环对Array里的元素以action方法进行处理
源码解读:
forEach函数也是Array中的一个扩展函数,而action可以为任意同以element为参数的函数
- flatMap:平铺元素为数组的数组
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 <T, R> Iterable<T>.flatMap(transform: (T) -> Iterable<R>): List<R>
return flatMapTo(ArrayList<R>(), transform)
//可以看到,与map不一样的是flatMap的作为参数的函数[transform]返回的不是单纯的数据R而是一个R的集合[Iterable],而flatMap本身的返回值同map一样是一个List<R>
//再看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 <T, R, C : MutableCollection<in R>> Iterable<T>.flatMapTo(destination: C, transform: (T) -> Iterable<R>): 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:对数组通过特定方法进行累计计算,初始值为数组第一个值
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 <S, T : S> Iterable<T>.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:对数组通过特定方法进行累计计算,初始值通过调用方法指定
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 <T, R> Iterable<T>.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:通过特定方法(规则),过滤某些元素,返回一个新的list集合
filter:vi 过滤,筛选;adj 过滤器,滤波器
filter方法源码:
/**
* Returns a list containing only elements matching the given [predicate].
* 返回仅包含与给定[predicate]匹配的元素的列表。(谷歌翻译)
*/
public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T>
return filterTo(ArrayList<T>(), predicate)
很明显这是一个过滤器方法,通过[predicate]方法过滤掉不符合规则的元素,返回一个新的list
由此,我们可以编写示例方法,比如,我们要筛选出列表中的偶数
val evenList = flatList.filter
it%2 == 0
evenList.forEachprint("$it,")
运行结果
2,2,4,2,4,6,
- takeWhile:
takeWhile:v 拿走
takeWhile方法源码:
/**
* Returns a list containing first elements satisfying the given [predicate].
* 返回包含满足给定方法[predicate]的第一个元素的列表。(谷歌翻译)
* @sample samples.collections.Collections.Transformations.take
*/
public inline fun <T> Iterable<T>.takeWhile(predicate: (T) -> Boolean): List<T>
val list = ArrayList<T>()
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.forEachprint("$it,")
运行结果:
1,2,3,2,3,4,
let/apply/with/use
这几个函数都是为了简洁化代码而设计的,篇幅原因,这里不做详解(懒!!!)
以上是关于kotlin学习之高阶函数及常用基本高阶函数的主要内容,如果未能解决你的问题,请参考以下文章