Lambda作为形参和返回值

声明高阶函数

  • 任何以lambda或者函数引用作为参数的函数,或者返回值,或者两者都有,就是高阶函数。比如list.filter
    (4,"abc")-> {} 如下:

{ x, y -> x + y} 这里省略了参数x,y类型,因为在其他部分已经制定了,不需要在lambda函数体再次声明

val funOrNull: ((Int, Int) -> Int)? = null
复制代码
  • 可以为函数参数制定名字
//声明
fun performRequest(url: String,callback: (code: Int, content: String) -> Unit
){}
//调用
val url = "http://baidu.com"
performRequest(url,{code, content -> /*code*/ })
performRequest(url){code, content -> /*code*/ }//根据kotlin约定,lambda为最后一个参数,可以放到括号外面
复制代码
  • 调用函数
//声明一个函数,参数为一个函数,这个函数有2个参数都是int值,返回值也为int
fun towAndThree(operator: (x: Int, y: Int) -> Int) {//这里的x,y是可以省略的,省略了,IDE代码补全会不方便val result = operator(3, 4)print("the result is $result")
}
复制代码
  • filter()函数
//声明
public inline fun <C : Appendable> CharSequence.filterTo(destination: C, predicate: (Char) -> Boolean): C {for (index in 0 until length) {val element = get(index)if (predicate(element)) destination.append(element)}
return destination
}
//调用
println(url.filter { it in 'a'..'z' })
复制代码
  • 在Java中使用函数类 原理:函数类型被声明为普通的接口:一个函数类型的变量,是FunctionN接口的一个实现。Kotlin标准库定义了一系列的接口比如 Function0<R>(没有参数的函数),Function1(P1,R)(一个参数的函数),调用这个方法就会执行函数。一个函数类型的变量就实现了对应的FunctionN接口的实现类的实例,实现类invoke方法包含了lambda函数体
//kotlin声明
fun processTheAnser(f: (Int) -> Int){}
//java 调用 java 8
processTheAnder(num->num+1)
//在Java8以下的版本这样调用
procressTheAnder{new Function1<Integer,Integer>(){@Overridepublic Integer invoke(Integer number){return number + 1}}
}
复制代码

函数类型的参数默认值和null

fun <T> Collection<T>.joinToString(separator: String = ", ",prefix: String = "",postfix: String = ""
): String {val result = StringBuilder(prefix)for ((index, value) in this.withIndex()) {if (index > 0) result.append(separator)result.append(value.toString())}result.append(postfix)return result.toString()
}
复制代码

返回函数的函数

  • 比如运输费用依赖于运输方式,可以定义一个函数,用来选择恰当的逻辑变体,并将它作为一个函数返回
fun getShoppingCarCacul(delivery: Delivery): (Order) -> Double {if (delivery == Delivery.STANDARD) {return { order: Order -> 6 + 2.1 * order.itemCont }}return { order -> 1.2 * order.itemCont }
}
//调用
var shoppingCarCacul = getShoppingCarCacul(Delivery.EXPEDITED)
println("产生的运费:${shoppingCarCacul(Order(4))}")
复制代码
  • eg:通过输入开头文字,过滤联系人列表
data class Man(val firstName: String,val lastName: String,val phoneNumber: String?
)class ContactListFilter() {val prefix = ""val isOnlyPhoneNumber = falsefun qetPredicate(): (Man) -> Boolean {val startWithPrefix = { man: Man -> man.firstName.startsWith(prefix) || man.lastName.startsWith(prefix) }//这里不能使用it,因为IDE推断不出it代表是什么if (!isOnlyPhoneNumber) {return startWithPrefix}return { man: Man -> startWithPrefix(man) && man.phoneNumber != null }//这里可以是用it,这里是根据方法的返回值类型,推断出it代码得man}
}
//调用val mans = listOf(Man("Bob", "jack"), Man("BooBo", "jack", "13800138000"), Man("kk", "jack", "13800138000"))val contactListFilter = ContactListFilter()with(contactListFilter) {prefix = "B"isOnlyPhoneNumber = false}
println(mans.filter(contactListFilter.qetPredicate()))
复制代码

使用lambda去除重复代码

 val log = listOf(SiteVisit("/", 34.0, OS.WINDOWS),SiteVisit("/", 22.0, OS.MAC),SiteVisit("/", 12.0, OS.WINDOWS),SiteVisit("/sign_up", 8.0, OS.IOS),SiteVisit("/", 16.3, OS.ANDROID))
fun List<SiteVisit>.averageTime(os: OS) = filter { it.os == os }.map { it.duration }.average()//调用
println(log.averageTime(OS.WINDOWS))
复制代码
  • 如果说要查询WINDOW、和Android的呢?后面又需要改成来自iOS的注册页面停留时间是多少呢?这个时候lambda就派上用场了。
fun List<SiteVisit>.averageTime(predicate: (SiteVisit) -> Boolean) = filter(predicate)//这里的筛选改为lambda。.map { it.duration }.average()
复制代码

把过滤条件转换成lambda表达式,实现去除重复代码
策略模式(你需要声明一个接口,并且为每一种可能实现不同的策略)可以通过lambda简化

内联函数:消除lambda运行时带来的开销

在kotlin中,每创建一个lambda表达式就会创建一个匿名类,so,每次调用都会创建一个对象,会带来额外的开销这个时候inline就出现了。
一个被inline修饰的函数,函数体会直接替换到函数被调用的地方,而不是正常调用。一般来说,参数如果被直接调用或者作为参数传递给另外一个inline函数。他是可以被内联的。

  • 内联函数使用限制-》不能把内联函数保存到一个属性?

内联集合操作

Kotlin标准库中,集合函数,比如filtermap等函数已经inline函数,不会产生额外的对象。在处理比较大的集合,应该使用序列asSequence进行操作。

怎样决定是否使用lambda

  • 使用inline关键字只能提高带有lambda参数的函数的性能。
  • 对于普通函数JVM已经提供了强大的内联支持。
  • 应该保证inline修饰的函数比较小。-》因为需要把函数字节码拷贝到每一个调用点上。

使用lambda管理资源

通常在资源管理中,需要在try里获取资源,在finally中释放资源可以把这一部分封装成lambda表达式 在Kotlin中,加锁使用withLock函数 :try-with-resource 语句

static String readFirstLineFromFile(String path) throws IOException {try (BufferedReader br = new BufferedReader(new FileReader(path))) {return br.readLine();}//这里不需要写关闭资源的语句,
}
复制代码

在Kotlin中使用use实现相同的结果,用于操作可关闭的资源。

fun readFirstLineFromFile(path: String): String = BufferedReader(FileReader(path)).use { br -> br.readLine() }
复制代码

高阶函数中的控制流

  • 使用return 从一个封闭的函数中返回。
val list = listOf(Person("Bob", 18, 20000), Person("Jack", 19, 20000))list.forEach {if (it.name=="Bob") {println("Found!")return //直接返回方法}}
复制代码
  • 从lambda返回
val list = listOf(Person("Bob", 18, 20000), Person("Jack", 19, 20000))list.forEach {if (it.name=="Bob") {println("Found!")return@forEach //直接返回方法}}
复制代码

同样的规则也适用于this表达式

  • 匿名函数:默认使用局局部返回
list.forEach {if (it.name=="Bob") returnprintln("Found!")}
复制代码

filter中使用匿名函数

    list.filter(fun(person): Boolean {return person.age > 10})
复制代码

如果是使用表达式函数体,可以省略返回值类型,可以简化为

list.filter(fun(person) = person.age > 10
)
复制代码

End

转载于:https://juejin.im/post/5c3d728af265da61171cf3c3

Kotlin 学习笔记08相关推荐

  1. Kotlin 学习笔记(八)—— Kotlin类与对象之接口

    Kotlin 学习笔记(八)-- Kotlin类与对象之接口 Kotlin学习笔记系列教程 Kotlin 学习笔记(一)-- 概述.学习曲线.开发工具.参考资料 Kotlin 学习笔记(二)-- 基础 ...

  2. JavaWeb黑马旅游网-学习笔记08【旅游线路详情】

    Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...

  3. Kotlin学习笔记(3)- 语法

    系列文章全部为本人的学习笔记,若有任何不妥之处,随时欢迎拍砖指正.如果你觉得我的文章对你有用,欢迎关注我,我们一起学习进步!kotlin学习笔记系列首发简书和CSDN Kotlin学习笔记(1)- 环 ...

  4. Kotlin学习笔记(2)- 空安全

    系列文章全部为本人的学习笔记,若有任何不妥之处,随时欢迎拍砖指正.如果你觉得我的文章对你有用,欢迎关注我,我们一起学习进步!kotlin学习笔记系列首发简书和CSDN Kotlin学习笔记(1)- 环 ...

  5. Kotlin学习笔记(1)- 环境配置

    系列文章全部为本人的学习笔记,若有任何不妥之处,随时欢迎拍砖指正.如果你觉得我的文章对你有用,欢迎关注我,我们一起学习进步!kotlin学习笔记系列首发简书和CSDN Kotlin学习笔记(1)- 环 ...

  6. kotlin学习笔记——枚举、封闭类

    1.枚举 kotlin中提供类枚举的实现,与java相同.枚举可以带参数,如 enum Icon(val res: Int){MENU(R.drawable.menu),BACK(R.drawable ...

  7. kotlin学习笔记——重载操作符

    Kotlin中有很多操作符可以使用,具体可以见kotlin学习笔记--操作符_There is a Bug!!!-CSDN博客 Kotlin的一个特点就是可以重载这些操作符,为操作符赋予不同的行为. ...

  8. Kotlin 学习笔记(七)—— Kotlin类与对象之属性与字段

    Kotlin 学习笔记(七)-- Kotlin类与对象之属性与字段 Kotlin学习笔记系列教程 Kotlin 学习笔记(一)-- 概述.学习曲线.开发工具.参考资料 Kotlin 学习笔记(二)-- ...

  9. Kotlin学习笔记20 阶段复习2

    参考链接 示例来自bilibili Kotlin语言深入解析 张龙老师的视频 lambda表达式 内联函数 Kotlin学习笔记 第三章 函数 高阶函数 lambda表达式 内联函数_积跬步 至千里- ...

最新文章

  1. 这家公司向苹果索赔百亿!一场鏖战八年的专利之争仍未结束
  2. thinkphp php resque,麻花儿
  3. 节点相似性与链路预测
  4. 【Android】Android模拟器无法上网问题
  5. object references an unsaved transient instance - save the transient instance before flushing .
  6. linux shell 脚本 supress,Linux指令和shell脚本
  7. 那个拒绝北大教授,却坚持留在美国做服务员的数学天才,现状如何
  8. 例题 2 最敏捷的机器人
  9. 转: ASP.NET2.0_缓存
  10. java声明_Java继续声明
  11. oem 无法访问问题解决过程
  12. jQuery基础--选择器
  13. javascript_core之正则、Math、Date
  14. 三相pwm整流器。采用电压电流双闭环,SVPWM调制
  15. Python基础更新
  16. html文本如何逐渐淡入,CSS如何实现文字淡入效果
  17. c#对使用US7ASCII的oracle存取中文的问题
  18. 搭建企业级微信公众号管理平台(三)----注册码实现与校验,Redis存储
  19. UE<C++>三步在C++中制作射击类游戏(射线检测、接口调用)
  20. flying-saucer-pdf预览及下载

热门文章

  1. 计算机专业会议评级,2018计算机专业工程教育认证研讨会
  2. 结果显示窗口如何缩小_Proe草绘时提示“截面再生失败。不合适的尺寸”如何处理?...
  3. 武汉超级计算机中心,加快打造“五个中心” 武汉率先开建人工智能计算中心...
  4. java中br.readline_Java:java中BufferedReader的read()及readLine()方法的使用心得
  5. oracle11g中的join,sql - 使用Oracle 11g中的+符号进行左外连接
  6. 一道很简单的贪心算法题~【贪心:我不要脸的伐?】
  7. 数据结构课上笔记10
  8. 橙白oj18训练作业2-题解、代码
  9. 《Python Cookbook 3rd》笔记(3.3):数字的格式化输出
  10. python输入程序_python程序的输入输出(acm的几个小程序)