zoukankan      html  css  js  c++  java
  • kotlin开发 高阶函数学习与记录

    前言

      开个新坑,以后会慢慢更新..

      此博客将讲解高阶函数的学习使用与实际使用的例子记录.

      了解高阶函数,需要了解一个关键概念: 高阶函数与lambda表达式的关系密不可分. 怎么理解这句话呢? 

       我们可以先可以看看普通函数与高阶函数的区别,普通函数的参数使用实例  高阶函数的参数使用lamdba表达式,如下代码中可以查看

      普通函数: 

           这是一个String类里的普通函数, 这里我们可以看到 函数的参数是一个IntRange类实例, 返回值是一个String

    public fun CharSequence.substring(range: IntRange): String = subSequence(range.start, range.endInclusive + 1).toString()

      高阶函数:

      这是一个String类里的高阶函数, 这里我们可以看到 函数的参数是一个lamdba表达式, 返回值是一个String

    public inline fun String.filter(predicate: (Char) -> Boolean): String {
        return filterTo(StringBuilder(), predicate).toString()
    }

    对比后我们可以这么理解下一个问题,将lamdba作为参数的优势是什么?

    1.lamdba作为参数可以表现出很大的灵活性,允许你在里面实现代码逻辑后返回参数

    2.符合人类的阅读习惯,易于阅读(前提是你不要嵌套大量的代码与大量的其他高阶函数) . 在设计良好的高阶函数上可以体验到读文本小说的方式进行阅读代码

         

    参考 简单理解 Kotlin 中的 inline 关键字

    参考 Kotlin inline, noinline and crossinline

     

    高阶函数实践例子

    根据传入集合里的时间戳字段,查找一天中最大的时间戳item,并且收集成集合返回

    public inline fun <T> Iterable<T>.findTheDailyMaxTimestamp(crossinline predicate: (T) -> Long): List<T> {
        var currentDayTime = 0L
        val timestampArray = this.toMutableList()
        timestampArray.sortByDescending { predicate(it) }
        val returnList = mutableListOf<T>()
        for (item in timestampArray) {
            //这里是关键,从实体类中去得参数里指引的目标的字段
            val time = predicate(item)
            if (currentDayTime == 0L) {
                currentDayTime = time
                returnList.add(item)
                continue
            }
            val currentCalendar = Calendar.getInstance()
            currentCalendar.timeInMillis = currentDayTime
            val crtYear = currentCalendar.get(Calendar.YEAR)
            val crtDay = currentCalendar.get(Calendar.DAY_OF_YEAR)
            val itemCalendar = Calendar.getInstance()
            itemCalendar.timeInMillis = time
            val itemYear = itemCalendar.get(Calendar.YEAR)
            val itemDay = itemCalendar.get(Calendar.DAY_OF_YEAR)
            if (crtYear == itemYear && crtDay == itemDay) {
                continue
            }
            currentDayTime = time
            returnList.add(item)
        }
        return returnList
    }

    使用了 扩展函数 加 内联函数, 在一些需要查找一天里需要显示日期的数据集合使用,特别适合在下面图片中情景下使用(稍微改造还能变成按月查找)

    使用:

    val findList: List<FamilyBean> = mList.findTheDailyMaxTimestamp { it1 -> it1.createTime }

    两个集合字段对比的函数

    多参数判空例子

    在kotlin多个参数的判空非常讨厌,需要多层嵌套let函数. 这里我们可以实现一个多参数判空的函数,优化这种代码

    /**
     * 参数不等于null就执行
     */
    fun <T1, T2> notNullLet(obj1: T1?, obj2: T2?, let: (T1, T2) -> (Unit)) {
        if (obj1 != null && obj2 != null) {
            let(obj1, obj2)
        }
    }
    
    /**
     * 参数不等于null就执行
     */
    fun <T1, T2, T3> notNullLet(obj1: T1?, obj2: T2?, obj3: T3?, let: (T1, T2, T3) -> (Unit)) {
        if (obj1 != null && obj2 != null && obj3 != null) {
            let(obj1, obj2, obj3)
        }
    }
    
    /**
     * 参数不等于null就执行
     */
    fun <T1, T2, T3, T4> notNullLet(obj1: T1?, obj2: T2?, obj3: T3?, obj4: T4, let: (T1, T2, T3, T4) -> (Unit)) {
        if (obj1 != null && obj2 != null && obj3 != null && obj4 != null) {
            let(obj1, obj2, obj3, obj4)
        }
    }

    使用:

            val deviceState = mLockViewModel.deviceStateResult.value
    
            notNullLet(mLockViewModel.currentBleDeviceInfo?.functionList,
                    deviceState,
                    mLockViewModel.currentFamilyDevice?.deviceSn) { functionList, deviceState, deviceSn ->
                mCatEyeUserListViewModel.postPasswordData(deviceSn, deviceState, functionList)
                showLoadingDialog()
            }

    End

  • 相关阅读:
    数据库使用时应该避开的坑
    Linux 命令 curl 的用法及参数解析
    分析 Redis 是否适合作为消息队列
    WEB框架对比——Django、Flask、FastAPI
    视频下载神器——you-get
    QtScrcpy——开源的电脑控制手机(投屏+控制)软件
    Python库大全
    Docker 清理数据卷 volumes
    报错解决——失败
    微信电脑端多开
  • 原文地址:https://www.cnblogs.com/guanxinjing/p/15630095.html
Copyright © 2011-2022 走看看