Kotlin基础学习第6章—高阶函数

一丶高阶函数

package chapter01

// region + 折叠
fun main(){

    /*高阶函数的调用*/
    //如果括号里的函数类型作为最后一个参数,可移到括号外面
    //it 是Lambda的特性
    intArray.forEach(){
        println("Hello $it")
    }
    //等价于
    intArray.forEach{
        println("Hello $it")
    }

}
// endregion




    /*高阶函数*/
// region + 折叠
//特征一:  block:()->Unit  ——  参数包含函数类型
//特征二:返回值为函数类型
fun needsFunction(block:()->Unit){
    block()
}
// endregion

//  常见的高阶函数一:
//IntArray.forEach  ——  扩展方法
//action:(Int) -> Unit  ——  接收函数类型作为参数
inline fun IntArray.forEach(action:(Int) -> Unit):Unit{
    //action(element)   ——  调用函数action
    for(element in this) action(element)
}

//  常见的高阶函数二:
//R ——  返回值元素类型
//transform:(Int)->R    ——  接收函数类型作为参数
inline fun <R>IntArray.map(transform:(Int)->R):List<R>{
    //transform ——  进一步传递 transform
    return mapTo(ArrayList<R>(size),transform)
}

在这里插入图片描述

二丶内联函数

package chapter02

fun main(){

    /*内联函数的概念*/
    //通过 inline标记
    val ints = intArrayOf(1,2,3,4)
    ints.forEach {
        println("Hello $it")
    }

    /*内敛高阶函数的return*/
    val ints = intArrayOf(1,2,3,4)
    ints.forEach {
        //return@forEach 跳出这一次内联函数调用 与 Java Continue 一样
        if (it == 3)return@forEach
        println("Hello $it")
    }



    /*non-local return*/
    nonLocalReturn {
        return //△表示:并不是退出Lambda表达式,而是从 外部 函数(main)返回
    }

}

inline fun IntArray.forEach(action:(Int)->Unit):Unit{
    for (element in this) action(element)
}





    /*定义内联函数*/
inline fun hello(){
    println("Hello")
}




    /*non-local return*/
inline fun nonLocalReturn(block:()->Unit){
    block()
}

    /*non-local return*/
    //不合法的情况
inline fun Runnable(block: () -> Unit):Runnable{
        return object :Runnable{
            override fun run() {
                //不合法处
                原因:
                1、有可能存在不合法的 non-local return
                2、因为 block 的调用处与定义处不在同一个调用上下文
                //其实return 的是 run 而不是Runnable
                 block()
            }
        }
    }
    //解决方法一:
//禁止 non-local return
inline fun Runnable(crossinline block: () -> Unit):Runnable{
    return object :Runnable{
        override fun run() {
            block()
        }
    }
}
    //解决方法二:
//禁止函数参数被内敛
inline fun Runnable(noinline block: () -> Unit):Runnable{
    return object :Runnable{
        override fun run() {
            block()
        }
    }
}




    /*内联属性*/
//含义:  没有 backing-field 的属性 getter/setter 可以被内联
//举例:
var pocket.Double = 0.0
var money.Double
    inline get() = pocket
    inline set(value){
        pocket = value
    }




    /*内联函数的限制*/
//1、public/protected 的内联方法只能访问对应类的 public 成员
//2、内联函数的内联参数不能被存储(赋值给变量)
//3、内联函数的内联函数参数只能传递给其他内联函数参数

在这里插入图片描述

三丶几个有用的高阶函数

package chapter03

import java.io.File

fun main(){
    val person = Person("benny",20)

    //let举例:返回表达式结果
    // '::' 表示把一个方法当做一个参数,传递到另一个方法中进行使用,通俗的来讲就是引用一个方法
    person.let(::println)
    //run举例:返回表达式结果
    person.run(::println)
    //also举例:返回Receiver
    val person2 = person.also {
        it.name = "hhh"
    }
    //apply举例:返回Receiver
    val person3 = person.apply {
        name = "xxx"
    }

    //use举例:自动关闭资源
    File("build.gradle").inputStream().reader().buffered()
        .use {
            println(it.readLine())
        }


}


    /*几个有用的函数*/
//  let、run、also、apply、use
//举例


class Person(var name:String,var age:Int){

}

在这里插入图片描述

四丶集合变化与序列

package chapter04

import java.lang.StringBuilder

fun main(){
    /*filter 变换(序列)*/
    //Java版本:
    list.stream()
        .filter(e->e%2 == 0)
//    等价于
    //kotlin版本一:
    //asSequence()转换为懒汉式
    list.asSequence()
        .filter{it % 2 == 0}
    //kotlin版本二:
    list.filter{it % 2 == 0}




    /*map 变换*/
    //Java版本:
    list.stream()
        .filter(e->e%2 == 0)
    //kotlin版本一:
    list.map{it*2+1}
    //kotlin版本二:
    list.asSequence()
        .map{it*2+1}



    /*flatMap变换*/
//    flatMap概念:用一个元素映射成一个集合,再把这个集合拼接起来得到新的集合
//    Map概念:把里面的元素映射成新的元素,那么这些元素组成的集合就成为Map集合
//    写法一:
    val list = listOf(1,2,3,4)
    list.flatMap {
        (0 until it)
    }
        .joinToString().let(::println)

//    写法二:
    list.asSequence()       //将集合变成一个序列
        .flatMap {
        (0 until it).asSequence()   //结果也应该要变成一个序列
    }
        .joinToString().let(::println)



    /*集合的聚合操作举例*/
    //1、sum —— 所有元素求和
    //2、reduce 将元素一次按规则聚合,结果于元素类型一致
    //3、fold —— 给定初始化值,将元素按规则聚合,结果与初始化值类型一致
     /*fold操作*/
    //acc —— 每一次拼接后的结果
    //i —— 遍历的list集合里的每一个元素
    list.fold(StringBuilder()){
        //acc.append(i) —— 返回值类型为StringBuilder,作为下一个元素的 acc
        acc,i -> acc.append(i)
    }


    /*恶汉式举例*/
    //概念:会分别在filter里马上遍历List集合,在往下走到map集合时就会马上调用list进行映射,再到forEach
    //区别:filter{}与map{}还有flatMap{}会立即调用
    //代码运行结果:0 1 2 3 4 0 1 2 3 4 5 6 7 8
    list.filter {
        it % 2 == 0
    }.map {
        it * 2 + 1
    }.flatMap {
        0 until it
    }.forEach(::println)


    /*懒序列举例:*/
    //概念:集合里的元素只有通过了一个才能继续往下走
    //区别:forEach 时才会调用filter{}与map{}还有flatMap{}
    //forEach —— 在这里就像是一个钥匙,如果没有这句代码打开水管,那上面的三个函数就像被堵住一样都不会调用
    //代码运行结果:0 1 2 3 4 0 1 2 3 4 5 6 7 8
    list.asSequence()
        .filter {
            it % 2 ==0
        }.map {
            it *2 +1
        }.flatMap {
            (0 until it).asSequence()
        }.forEach(::println)

}

在这里插入图片描述

五丶SAM 转换

package chapter05

fun main(){
    //Java中的lambda表达式是没有自己的类型的,而且只能接口里只能有一个方法

    //kotlin实际上时创建一个 Runnable 包装了一下Lambda,并非直接转换
}

在这里插入图片描述

六丶案例:统计字符个数

package chapter06

import java.io.File


fun main(){
    //打开文件build.gradle,阅读文本,string 类型
    File("build.gradle").readText()
        .toCharArray()  //把它们char类型数组
        .filter { !it.isWhitespace() }  //过滤空白字符
        .groupBy { it } //it 是charArray里的每一个字符,通过it来分组,得到key 就是 char
        .map {
            it.key to it.value.size     //映射
        }.let {
            print(it)
        }
}

七丶案例:HTML SDL

八丶实践:体验 Gradle Kotlin DSL

九丶本章小结

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_27494201/article/details/106476248