前言
本博客为本人学习笔记,如有不对的地方,劳请在评论区指出,望海涵
Kotln 学习笔记(八)
参考文章
说到lambda 简单的说,就是 匿名函数。我这里通过代码展现 不同的表达方法
// 比较常规易懂的 写法 fun (a :Int , b : Int):Int{ return a + b } // 单句表达式 可以直接 用 = 省略 大括号 fun (a :Int , b : Int):Int = a + b // 智能类型 fun (a :Int , b : Int) = a + b // 原始版 Lambda 表达式 val lambda = {// 传入的类型 及 参数 a : Int , b : Int// -> 分割 输入和 输出 ->// 结果输出 a+b } // lambda 表达式。两种引用方法都对,其实本质一样的 println(lambda(2,3)) println(lambda.invoke(2,3))
12345678910111213141516171819202122232425262728293031323334lambda的标准形式基本声明满足三个条件:
含有实际参数 ( a : Int , b : Int )含有函数体(尽管函数体为空,也得声明出来) ( a+b)以上内部必须被包含在花括号内部当然 大多数 匿名类 都是 一个参数的,我们这里暂时使用一个参数的 lambda 方程式进行 不断的 简单 展示。
// 声明 var sum : ((Int) -> Int)? = null // 实现 // {参数 :参数类型 -> 返回值(具体逻辑)} sum ={x : Int -> x*2} // 由于知道了出入类型 我们也可以省略 参数类型 sum ={x -> x*2} // 由于我们使用的 一个参数,参数可以写为 it sum ={it*2} // 该lambda 表达式错误的,其内 不能直接使用 return sum ={ it*2 return } // lambda 最后一个表达式就是 该表达式的返回值 sum ={ println("$it") it*2 }
12345678910111213141516171819202122232425注意事项
注意:语法简化是把双刃剑,简化固然不错,使用简单方便,但是不能滥用,也需要考虑到代码的可读性.。
前面我们说到 不能再 lambda 表达式中使用 return ,当然不是绝对,我们使用 return+label;
// 声明一个没有返回值的 var demo : ((Int) -> Unit)? = null demo = die@{ it *2 return@die } 1234567
高级函数其实还是函数,只不过 方法的参数可以为函数,返回值也可以是函数。我们使用例子来看下 高级函数
// 函数第二个参数为 lambda函数 fun play(girl :String , shop : () ->Unit):Unit{ println("the girl is $girl") fun todoSomething () :Unit{ shop() println("todoSomething start") } // 返回值也可以为函数 return todoSomething() } 123456789101112131415
解释:
在kotlin中,函数是一种类型,所以我们可以把一个具体的函数当成对象。
既然函数是一个对象啦,我们想怎么玩这个对象就怎么玩。
比如:
接下来我们看下 高级函数的调用
fun shopImpl():Unit{ println("hello world") } // 调用普通函数 play("gyy",:: shopImpl) // 传入lambda 函数 play("gyy",{ println("hello world !")}) 1234567891011
通过上面的学习,我们写一个 扩展函数 并简单的运用下 高级函数
// 扩展函数 传入lambda 函数 fun List<Int>.initList(double: (Int) -> Int): List<Int> { var resultList = arrayListOf<Int>() // 循环 将集合item 都带入lambda 函数中 for(item in this){ resultList.add(double(item)) } return resultList } var oneList = arrayListOf<Int>(1,2,3) // 默认调用List 的tostring 方法 println(oneList) // 调用并定义 lambda 函数 var twoList = oneList.initList { it * 2 } println(twoList)
12345678910111213141516171819202122打印结果‘
[1, 2, 3] [2, 4, 6] 12 2.2 lambda表达式类型
Kotlin中提供了简洁的语法去定义函数的类型.
() -> Unit//表示无参数无返回值的Lambda表达式类型
(T) -> Unit//表示接收一个T类型参数,无返回值的Lambda表达式类型
(T) -> R//表示接收一个T类型参数,返回一个R类型值的Lambda表达式类型
(T, P) -> R//表示接收一个T类型和P类型的参数,返回一个R类型值的Lambda表达式类型
(T, (P,Q) -> S) -> R//表示接收一个T类型参数和一个接收P、Q类型两个参数并返回一个S类型的值的Lambda表达式类型参数,返回一个R类型值的Lambda表达式类型
可能部分读者 对于前几个 表达式类型还可以理解,这里主要说下 最后一个
(T, (P,Q) -> S) -> R :
从外到内 来说明 (T , X)-> RX 可以理解为 (P,Q) -> S如果 多个lambda表达式,但是这些lambda表达式的类型很多相同,我们就很容易把所有相同一大串的Lambda类型重复声明或者你的lambda类型声明太长不利于阅读。实际上不需要,对于Kotlin这门反对一切啰嗦语法的语言来说,它都给你提供一系列的解决办法,让你简化代码的同时又不降低代码的可读性。
举个例子
fun main(args: Array<String>) { fun List<Int>.initList(double: (Int) -> Int): List<Int> { var resultList = arrayListOf<Int>() // 循环 将集合item 都带入lambda 函数中 for(item in this){ resultList.add(double(item)) } return resultList } val oddNum: (Int) -> Unit = { if (it % 2 == 1) { println(it) } else { println("is not a odd num") } } val evenNum: (Int) -> Unit = { if (it % 2 == 0) { println(it) } else { println("is not a even num") } } oddNum.invoke(100) evenNum.invoke(100) var oneList = arrayListOf<Int>(1,2,3) // 默认调用List 的tostring 方法 println(oneList) // 调用并定义 lambda 函数 var twoList = oneList.initList { it * 2 } println(twoList) }
12345678910111213141516171819202122232425262728293031323334353637383940使用typealias关键字声明(Int) -> Unit 和 (Int) -> Int 类型
package com.ymc.kotlindemo import android.os.Bundle // typealias 声明 关键字 typealias NumPrint = (Int) -> Int typealias Num2Print = (Int) -> Unit fun List<Int>.initList(double: NumPrint): List<Int> { var resultList = arrayListOf<Int>() // 循环 将集合item 都带入lambda 函数中 for(item in this){ resultList.add(double(item)) } return resultList } val oddNum: Num2Print = { if (it % 2 == 1) { println(it) } else { println("is not a odd num") } } val evenNum: Num2Print = { if (it % 2 == 0) { println(it) } else { println("is not a even num") } }
1234567891011121314151617181920212223242526272829303132 4. kotlin 使用场景参考文章
场景一: lambda表达式与集合一起使用,是最常见的场景,可以各种筛选、映射、变换操作符和对集合数据进行各种操作,非常灵活。
fun main(args: Array<String>) { val nameList = listOf("Kotlin", "Java", "Python", "JavaScript", "Scala", "C", "C++", "Go", "Swift") nameList.filter { it.startsWith("K") }.map { "$it is a very good language" }.forEach { println(it) } } 123456789101112
场景二: 替代原有匿名内部类,但是需要注意一点就是只能替代含有单抽象方法的类。
我们用java 写的 方式 如下
findViewById(R.id.submit).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {...}}); 1234567
但是如果使用 lambda
findViewById(R.id.submit).setOnClickListener{ ... } 1234
场景三: 定义Kotlin扩展函数或者说需要把某个操作或函数当做值传入的某个函数的时候。
fun Context.showDialog(content: String = "", negativeText: String = "取消", positiveText: String = "确定", isCancelable: Boolean = false, negativeAction: (() -> Unit)? = null, positiveAction: (() -> Unit)? = null) {AlertDialog.build(this).setMessage(content).setNegativeButton(negativeText) { _, _ ->negativeAction?.invoke()}.setPositiveButton(positiveText) { _, _ ->positiveAction?.invoke()}.setCancelable(isCancelable).create().show() } fun Context.toggleSpFalse(key: String, func: () -> Unit) {if (!getSpBoolean(key)) {saveSpBoolean(key, true)func()} } fun <T : Any> Observable<T>.subscribeKt(success: ((successData: T) -> Unit)? = null, failure: ((failureError: RespException?) -> Unit)? = null): Subscription? {return transformThread().subscribe(object : SBRespHandler<T>() {override fun onSuccess(data: T) {success?.invoke(data)}override fun onFailure(e: RespException?) {failure?.invoke(e)}}) }
1234567891011121314151617181920212223242526272829303132333435到这里 我对 lambda 和 高级函数的理解 已经总结完毕,如果有不足的地方,请观众老爷 积极评论。
Kotlin 学习笔记 (十)
相关知识
keras中Lambda层的使用
动手学深度学习笔记(一)
TensorFlow学习记录(八)
[机器学习基础][笔记] 一、鸢尾花分类
重磅!花书《深度学习》,这份精炼笔记可能是最全面的
4、算法诊断
Android 移动应用基础教程(Android Studio)(第2版)学习笔记及源码
Tensorflow学习笔记——搭建神经网络
【李刚
Keras学习笔记(二)Keras模型的创建
网址: Kotlin 学习笔记 (九) 可怕的 lambda 及 高级函数 https://m.huajiangbk.com/newsview793177.html
上一篇: 图集|数字人 + 虚拟场景 = |
下一篇: 用户增长=裂变?三千字给你讲清“ |