zoukankan      html  css  js  c++  java
  • Kotlin学习-函数(表达式,lambda,高阶函数)

    Kotlin中函数 3种表达形式:

    一般函数:

    fun sum(a: Int, b: Int): Int {
        return a+b
    }
    

    简化函数为表达式形式:

    fun sum2(a: Int, b: Int): Int = a + b //函数表达式
    fun max(a: Int, b: Int): Int = if(a > b) a else b //lambda函数
    fun isOdd(x: Int) = x % 2 != 0

    带默认参数的函数

    //函数参数可以指定默认参数
    fun multiply(a:Int,mut:Int=2):Int{
        var result = 1 
        for(i in 0..mut){
            result *= a
        }
        return result
    }
    

    lambda表达式函数定义:

    1. 无参数情况 :
    val/var 变量名 = { ... }
    2. 有参数情况
    val/var 变量名 : (参数的类型,参数类型,...) -> 返回值类型 = {参数1,参数2,... -> 操作参数的代码 }
    示例:val sumLambda: (Int, Int) -> Int = {x,y -> x+y}
    注:(Int,Int)=>Int为函数签名,(a:Int,b:Int)表示函数参数


    3,自动推导返回值类型(即表达式的返回值类型会根据代码实现块,推导出来)
    val/var 变量名 = { 参数1 : 类型,参数2 : 类型, ... -> 操作参数的代码 }
    示例:val sumLambda2 = {a : Int , b : Int -> a + b}

     例如:

    val sumLambda1: (Int, Int) -> Int = {x,y -> x+y}
    val sumLambda2 = {a : Int , b : Int -> a + b}
    

    高阶函数:apply/run/also/let/with

    kotlin标准库提供了Any对象上下文内执行一段代码块,可用于对象初始化,直接使用对象内部方法,使代码更精简化。

    run即可作用于Any,又可作为this代码块,run返回执行的是处理结果

        fun getIdentify(index:Int):String{
            val person_play = run {//将最后处理结果返回
                when(index){
                    0 -> "manager"
                    1 -> "guest"
                    2 -> "worker"
                    else -> "none"
                }
            }
            return person_play
        }
    
        fun getSampleNickName(nn:String):String{
            var sampleName = nn.run {
                if(this.length>10)
                  substring(0,this.length-6)
                else
                    nn
            }
            return sampleName
        }

     apply用法类似run,区别在于apply执行完成block()函数后,返回自身对象
     返回自身对象,可以使用链式方法使用.apply{}.apply{}

    val adam = Person("Adam").apply { 
        age = 20
        city = "London"
    }
    fun testApply(st:String){
    st.apply {
    println("result:${this.plus("-java")}")
    }.apply {
    println("result:${this.plus("-php")}")
    }
    }

    let内部使用it指代当前对象,返回最后一行处理结果, (T) -> R

     fun testLet(st:String?){
            st?.let {  // execute this block if not nul
                it.plus("-let1")
                if(it.startsWith("android"))
                    it.drop(8)
            }
    
            val listWithNulls: List<String?> = listOf("element1","element2", null)
            for (item in listWithNulls) {
                item?.let { // 元素不为空时执行
                    println(it)
                }
            }
        }

    与let函数相似,区别是also执行完成后返回对象本身,let返回处理结果

    fun testAlso() {
            val numberList = mutableListOf<Double>()
            numberList.also {
                println( "init the list")
            }.also {
                it.add( 2.71)
                it.add(3.14)
                it.add(1.0)
            }.also {
               println(  "Sorting the list")
            }.sort()
        }
    

    with函数作用于一个对象,返回最后一行处理结果

     fun testWith(){
            var p = Person("Tom", 26)
            //写法一,对象receiver和一个lambda函数块
            val result = with(p, {
                println("my name is $name, I am $age years old")
                1000
            })
            //由于with函数最后一个参数是一个函数,可以把函数提到圆括号的外部修改后
            val result2 = with(p) {
                println("my name is $name, I am $age years old")
                1000
            }
    
            val numbers = mutableListOf("one" , "two","three")
            with(numbers) {
                val firstItem = first()
                val lastItem = last()
                println("First item: $firstItem, last item:$lastItem")
            }
        }

    其它高阶函数

    fun fooLabel1() {
            listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) {
                if (value == 3) return  // local return to the caller of the anonymous fun, i.e. the forEach loop
                print(value)
            })
            print(" done with anonymous function")
        }
    
        fun fooLabel2() {
            listOf(1, 2, 3, 4, 5).forEach lit1@{
                if (it == 3) return@lit1 // local return to the caller of the lambda, i.e. the forEach loop
                print(it)
            }
            print(" done with explicit label")
        }
        fun fooLabel3() {//implicit label
            listOf(1, 2, 3, 4, 5).forEach {
                if (it == 3) return@forEach // local return to the caller of the lambda, i.e. the forEach loop
                print(it)
            }
            print(" done with implicit label")
        }
    
        fun fooLabel5() {
            run loop@{
                listOf(1, 2, 3, 4, 5).forEach {
                    if (it == 3) return@loop // non-local return from the lambda passed to run
                    print(it)
                }
            }
            print(" done with nested loop")
        }

    函数作为参数

    在kotlin中函数可以作为参数传递给另一个函数去执行

    例1:

     var globalLock = ReentrantLock()
        inline fun <T> lockInnerHandle(body: () -> T): T {//统一实现函数线程安全锁
            globalLock.lock()
            try {
                return body()
            }
            finally {
                globalLock.unlock()
            }
        }
    

     通过这种方式可以统一实现某些功能的形式,简化函数重复代码量,高阶函数 run/apply/let/also等也是将函数作为参数处理的

    例2:

    //function as param
    fun calFun(x:Int,y:Int,f:(Int,Int)->Int){
        val result = f(x,y)
        println(result)
    }
    //simple call
    calFun(2,3,(a:Int,b:Int)=>{a*b})
    

    函数引用

        fun isOdd(x: Int) = x % 2 != 0
        fun isOdd(s:String) = s =="kotlin"|| s =="java"|| s == "cpp"
        fun calLength(s:String ) = s.length
    
        val numbers = listOf(1,2,3)
            //normal invoke
            println(numbers.filter { isOdd(it) })
            //Function References ::调用
            println(numbers.filter(::isOdd))
    
    
    //组合函数使用
        fun composeFun(){
            val oddLength = compose(::isOdd, ::calLength)//compose(f, g) = f(g(*))
            val strings = listOf("a","ab" , "abc" )
            println(strings.filter(oddLength))
        }
        //组合函数定义
        fun <A, B, C> compose(f: (B)-> C, g: (A) -> B): (A) -> C {
            return { x -> f(g(x)) }
        }
    
    //显示指定参数的方法,调用
            val predicate: (String) -> Boolean = ::isOdd
            predicate("cpp")
    
    //调用类成员
     class A(val p:Int)
    
    //调用类的成员方法或扩展方法
      val prop = A::p
    
  • 相关阅读:
    Traefik使用
    kubernetes nfs-client-provisioner外部存储控制器
    基于腾讯云CLB实现K8S v1.10.1集群高可用+负载均衡
    k8s-rabbitmq-(一)集群部署
    TabSet 实现拖动后并保存配置
    C# MD5加密
    VSS “vc6.0vssum.dat may be corrupt”错误
    C#编程基础笔记
    android.view.WindowLeaked的解决办法
    【转】java线程系列---Runnable和Thread的区别
  • 原文地址:https://www.cnblogs.com/happyxiaoyu02/p/10689785.html
Copyright © 2011-2022 走看看