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.forEach{print("$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.forEach{print("$it,")}

运行结果:

1,2,3,2,3,4,

let/apply/with/use
这几个函数都是为了简洁化代码而设计的,篇幅原因,这里不做详解(懒!!!)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值