golang 网站开发/考研培训机构排名前五的机构
Lambda和高阶函数
本文链接:
文章目录
- Lambda和高阶函数
- lambda
- 输出(返回类型)
- 深入探究
- 泛型
- inline原理探究
- 高阶函数
- 集合、泛型
- 自己实现Kotlin内置函数
- 扩展函数原理
- companion object 原理 ==> 静态内部类
- 函数式编程
lambda
1、lambda的由来
- 单词"lambda"源于希腊字母λ(小写lambda)
- "Lambda"一词最早起源于数学中的λ演算(lambda calculus),它是一种函数定义和函数应用的形式系统,由逻辑学家阿隆佐·邱奇(Alonzo Church)在20世纪30年代发明。
- 邱奇使用λ作为演算中的一个操作符,用于表示匿名函数。他选择使用希腊字母λ的原因是因为它在字母表中的位置不太常见,这样可以避免与其他符号混淆。
2、函数的声明
// 函数的声明val method01:()->Unitval method02:(Int, Int)->Unitval method03:(String, Double)->Any // 相当于Objectval method04:(String, Double, Float)->Boolean
3、kotlin中Any和Java的Object有什么区别吗?
- Any是所有非空类型的超类型,类似于Java中的Object。Object不能持有null。
- Any?是所有类型的超类型,包括可空类型。
Any?可以持有null值
4、函数如何调用/函数的实现(lambda)?invoke是什么?
// 函数变量通过invoke()调用
// ()是运算符重载
// 函数的实现
val method01:()->Unit
method01 = { println("我实现了method01") }
method01() // 调用函数:操作符重载
method01.invoke() // 调用函数:真实方法// 方法三的实现
val method03:(String, Double)->Any // 相当于Object
method03 = {name, number ->println("$name $number")name + number
}
println(method03("wch", 1234567.89))
5、函数的实现(传入函数)
val method04:(String, Double, Float)->Boolean= fun(name:String, number:Double, age:Float):Boolean = (name+number+age).isEmpty()
method04("wch", 376.23, 1234.5f)
6、单一参数的lambda默认持有it ===> 函数式接口 ===> SAM
val method05:(Int)->Unit = {print("$it")}
7、下划线可以拒收 ===> 拒收
val method06:(Int, Int)->Unit = { _, number->println("$number")}
8、作用是什么?
- 节省空间
- 接口版本变化,有的参数没用了
9、想要允许参数为null,需要用可空类型如String?
val method07:(String?,String)->Unit = {sex, name -> println("$sex,$name")}method07(null, "wch")
10、Lambda不可以使用泛型作为参数类型
11、Lambda参数不可以给默认值 ===> 默认参数
12、Lambda Any->Any
// 传入什么,打印什么,还可以返回任何东西val method18:(Any)->Any={println("$it")it // 还可以返回自己}
13、Lambda配合扩展方法 ===> 扩展方法 ===> 官网写的Funciton,但是接收receiver
val method19: String.()->Unit = {// this = String本身 == 调用者本身println("你是$this")}"WCH".method19()
14、为什么method19可以成为String的扩展方法?
- 代码
val method19: String.()->Unit = { ... }
表示定义了一个接收者类型为String
的扩展函数类型。 String.()->Unit
表示该函数类型接收一个String
作为接收者,并返回Unit
类型(即没有返回值)。- 进一步理解:==> 匿名扩展函数
val method18: ()->Unit; // 类型是 函数
val method19: String.()->Unit // 类型是 String的扩展函数
val method20: (String)->Unit // 类型是 函数,该函数的参数是String
15、进一步融合this和it,区分扩展函数 和 参数的区别
val method20: Int.(Int) -> String = {"两数相加的结果:${this+it}"}
println(1.method20(10))println(method20(1, 10)) // 1, 可以自动插为第一个参数
函数的形式:
fun Int.method21(n:Int):String{return "两数相加的结果:${this+n}"
}
println(2.method21(22))
// println(method21(2, 22)) // 不可以这样写了
输出(返回类型)
1、Lambda的返回类型:函数
/**============================* 函数*============================*/// 默认Unitfun t01(){ println() }// 默认Unitfun t02(){4652342.5f}// 默认Unitfun t03(){"Hello!"}// String:显式指明返回值fun t04():String{return "feather"} // return 还不支持自动推断类型
2、函数返回函数
/**==============================* 函数返回函数*=============================*/// ()->Unitfun s01() = {}fun s02() = { println("Haha") }s02()() // 输出// Booleanfun s03() = run{ true }// 返回的是代码块的最后一行s03()// ()->Stringfun s04():()->String = {"Hello"}println(s04()) // Function0<java.lang.String>println(s04()())
3、Java中Lambda是假的
深入探究
4、Lambda深入探究
// k01()返回的类型是: (Int)->Unitfun k01() = {n:Int -> println(n) }k01()(123)// lambda使用,第一种用的多val methodx2 = {str:String -> str.length}val methodx2s:(String)->Int = {it.length}
5、Kotlin的Lambda如何和Java兼容?源码机制
- kotlin编译器实现(很强大) -> JVM字节码
package kotlin.jvm.functions
中定义了Function系列- 最多Funciton22,高版本编译器可以处理>22个参数的情况,低版本会出错
// val methodx2 = {str:String -> str.length}
Function1 methodx2 = (Function1)null.INSTANCE;
// (String)->Unit
val method3:Function1<String, Unit> = { println(it) }
6、Lambda考题
//(Int,Int) -> (Int,Int) ->Stringval funX10 = fun(n1:Int,n2:Int):(Int,Int)->String={n1,n2 -> "两个数相加:${n1 + n2}"}println(funX10(10, 10)(20, 20))// 迷惑点,最外层的n1和n2和内层的n1 n2没关系
// 函数的函数的函数的函数val k01: (String) -> (Boolean) -> (Int) -> (Float) -> Double ={ it ->{ it ->{ it ->{ it ->123.456}}}}println(k01("AAA")(true)(45)(67.89f))
7、下面的study02()返回的类型是什么?
fun study02() = {lambda:(Int, Int) -> String, studyInfo: String ->lambda(1, 99)
}
// 答案:((Int, Int) -> String, String) -> Unit // 使用:
study02()({n1, n2-> "$n1 + $n2 = ${n1 + n2}" }, "wch")
8、下面study04()返回的类型是什么?
fun study04() = {str:String, num:Int, lambda1:(String)->Unit, lambda2:(Int)->Boolean->lambda1(str)lambda2(num)
}
// 答案:(String,Int,(String)->Unit,(Int)->Unit)->Boolean// 使用:
println(study04()("wch", 123, { println("$it lambda1") }, { it > 99}))
泛型
9、下面返回的类型是什么?
fun <T1, T2, R1, R2> study05() = {str:T1, num:T2, lambda1:(T1)->R1, lambda2:(T2)->R2 ->lambda1(str)lambda2(num)
}
// (T1, T2, (T1)->R1, (T2)->R2) -> R2// 使用:
study05<String, Int, Boolean, Float>()("wch", 22, {it.isEmpty()}, {it.toFloat()})
10、下面的study06不是lambda,是函数。他们的类型是什么?
fun study05() = {Str:String, num: Int, lambda:(Int)->Boolean ->lambda(num)
}
// (String, Int, (Int)->Boolean)->Booleanfun study06() = fun(Str:String, num: Int, lambda:(Int)->Boolean):Boolean{return lambda(num)
}
// (String, Int, (Int)->Boolean)->Boolean
- Lambda表达式,最后一行作为返回值
- 函数,最后一行不能作为返回值
- 必须显式return
- 必须显式指定
函数有隐式的Unit类型返回值
inline原理探究
1、Lambda为什么要内联?
- 不使用内联,会构造出Function0对象,作为参数传入
- 代码内联,减少方法调用开销,不再需要创建Function0对象 ===> 内存抖动
fun main() {show{println("Hello Kotlin!")}
}
fun show(lambda:()->Unit){lambda()
}
// 不使用内联生成代码:
show((Function0)null.INSTANCE);
public static final void show(@NotNull Function0 lambda) {Intrinsics.checkNotNullParameter(lambda, "lambda");lambda.invoke();
}
// 使用内联:
int $i$f$show = false;
int var1 = false;
String var2 = "Hello Kotlin!";
System.out.println(var2);
高阶函数
===> Compose内部实现,学习
1、高阶函数是什么?高阶函数 = lambda + 函数
fun a() {}
val a1 = {} // 函数引用,接收,匿名函数
val a2 = a1 // 函数引用
val a3 = ::a // 将函数变成函数引用
2、高阶函数就是函数的函数,函数中有lambda
// Lambda开胃菜// 返回Stringfun show01(number:Int, lambda:(Int)->String) = lambda.invoke(number)// 调用函数var r01 = show01(99){it.toString()}// return Intfun show02(n1:Int,n2:Int,n3:Int, lambda: (Int,Int,Int)->Int) = lambda(n1, n2, n3)show02(10, 20, 30){i, i2, i3 ->i + i2 + i3}
3、高阶函数例子
// 第一版,高阶函数应用
fun main() {loginEngine("wch", "123456")
}private fun loginEngine(name:String, pwd:String){loginServer(name, pwd){code, msg->print("错误码$code 错误信息$msg")}
}private fun loginServer(name:String, pwd:String, lambda:(Int, String)->Unit){if(name.isEmpty() || pwd.isEmpty()){lambda(-1, "Empty")return}lambda(1, "Success")
}
// 第二版
4、高阶函数
// (一)给泛型增加匿名扩展函数
fun<T> T.myRun01(block: T.(Float) -> Boolean) = block(123.45f)
// this = T本身 = 调用者本身 == Derry// 使用
"Derry".myRun01 {isEmpty()
}// (二)
fun<T> T.derry4(number:Double, mm: T.(Double) -> Unit){mm(number)
}
"Derry".derry4(123.456){// this = 调用者println(this)
}// (三)
fun<T> T.myRunPlus(block: T.(T, T) -> Boolean) = block(this,this)
5、T.() -> Boolean s是什么意思?
- 对T扩展出匿名函数
- 匿名函数是 ()->Boolean
- 该匿名扩展函数只有这个高阶函数可以使用,其他地方用不出来
6、多个lambda调用
// (一)
show2(lambda1 = {}, lambda2 = {})
//(二)
show2({}, {})
// (三)
show2({println("Hello")}){println("World!")
}
7、源码使用高阶函数,利用函数引用
show(::lambdaImpl)fun lambdaImpl(){println("HAHA")
}// 函数引用场景
fun lambdaImpl(name:String):Unit{println(name)
}
var r1:Function1<String, Unit> = ::lambdaImpl
var r2:(String)->Unit = ::lambdaImpl
var r3:String.()->Unit = ::lambdaImpl // (String)等价于String.()
集合、泛型
1、Lambda+集合+泛型
class AndroidClickListener<T>{// 1. 集合的元素类型是Lambda,并且Lambda输入参数的类型是 Tval actions = arrayListOf<(T)->Unit>()val actions2 = arrayListOf<(T?)->Unit>() // 可空// 2. 集合的元素类型为泛型val values = arrayListOf<T?>()// 3、设置监听fun addListener(value:T?, lambda:(T?)->Unit){values += value // 运算符重载actions2 += lambda}// 4、通知观察者fun notify(value:T?){val index = values.indexOf(value)actions2[index].invoke(value) // 执行方法actions2[index](value) // 执行方法二}// 5. 模拟点击事件,通知所有观察者fun touchListeners(){actions2.forEachIndexed{index, function -> function(values[index])}}
}// 使用,测试val click = AndroidClickListener<String>()click.addListener("HaHa"){println("接收到数据:$it")}click.addListener("WCH"){println("$it 在吃饭中...")}click.addListener("Feather"){println("百万博客主:$it")}click.touchListeners()// 函数引用版本fun method(value:String?){println(value)}click.addListener("Hello", ::method)
2、如何用变量接收类型中包含泛型的函数?
fun<T> method(value: T?):Unit{println(value)
}// 不可以用泛型
// val error:(T?)->Unit = ::method// Any来代表T?val m1:(Any)->Unit = ::methodm1("Hello")// 具体类型也可以val m2:(Int)->Unit = ::methodm2(123)
自己实现Kotlin内置函数
1、forEach
// 定义
inline fun<E> Iterable<E>.mForEach(lambda:(E)->Unit){for(item in this)lambda(item)
}// 使用
listOf("AAA", "BBB", "CCC").mForEach{println(it)}
2、let和run,为什么会有this,为什么会有it
- this,it
- T.()->R, this是对T的匿名扩展函数,拥有this
- (T)->R,it是参数类型,SAM单一抽象接口,函数式接口,it
public inline fun <T, R> T.run(block: T.() -> R): R {return block()
}
public inline fun <T, R> T.let(block: (T) -> R): R {return block(this)
}
3、thread
- 注意点: corssinline
// 自己实现thread,特定lambda不能inline
inline fun thread(start:Boolean = true,name:String?=null,crossinline runAction:()->Unit // 限制不能inline,会copy大量代码
):Thread{val thread = object:Thread(){override fun run() {super.run()runAction()}}if(start) thread.start() // name?.let { thread.name = it } // kotlin形式return thread
}
扩展函数原理
1、扩展函数就是构造static final方法,将对象作为返回值
class MyKt {}
fun MyKt.show() = println(this)
public final class MyKt {}
// 构造出Kt类,添加扩展函数名一样的static final方法,将类的对象作为参数
public final class MyKtKt {public static final void show(@NotNull MyKt $this$show) {Intrinsics.checkNotNullParameter($this$show, "$this$show");System.out.println($this$show);}
}
2、思考:叫做扩展函数是否是因为没有receiver?
companion object 原理 ==> 静态内部类
1、为什么叫伴生对象?
- 生成静态内部类
- 生成静态成员变量(类变量)
- 通过伴生对象实例,调用方法和获取字段
2、使用处
class MyKt {companion object{fun show(){println(this)}val name = "wch"}
}fun main() {MyKt.show()MyKt.name
}
3、反编译,生成源码
- 生成静态内部类,Companion,并且有show()方法和字段name
- 类中Companion实例,是static final变量
- 像Java一样调用类方法和获取类属性,本质通过Companion伴生对象,调用方法和get字段
public final class MyKt {private static final String name = "wch";public static final Companion Companion = new Companion((DefaultConstructorMarker)null);public static final class Companion {public final void show() {System.out.println(this);}public final String getName() {return MyKt.name;}private Companion() {}// $FF: synthetic methodpublic Companion(DefaultConstructorMarker $constructor_marker) {this();}}
}// 使用处
MyKt.Companion.show();
MyKt.Companion.getName();
函数式编程
Kotlin函数式编程
- 链式调用
- 非常丰富的函数库
- 模仿RxJava的响应式编程
相关文章:

Kotlin Lambda和高阶函数
Lambda和高阶函数 本文链接: 文章目录 Lambda和高阶函数 lambda输出(返回类型)深入探究泛型 inline原理探究 高阶函数集合、泛型自己实现Kotlin内置函数 扩展函数原理companion object 原理 > 静态内部类函数式编程 lambda 1、lambda的由…...

ELKstack-Elasticsearch配置与使用
一. 部署前准备 最小化安装 Centos 7.x/Ubuntu x86_64 操作系统的虚拟机,vcpu 2,内存 4G 或更多, 操作系统盘 50G,主机名设置规则为 es-server-nodeX , 额外添加一块单独的数据磁盘 大小为 50G 并格式化挂载到/data/e…...

Kotlin 基础教程二
constructor 构造器一般情况下可以简化为主构造器 即: class A constructor(参数) : 父类 (参数) 也可以在构造器上直接声明属性constructor ( var name) 这样可以全局访问 init { } 将和成员变量一起初始化 susped 挂起 data class 可以简化一些bean类 比如get / set ,自动…...

K8S deployment挂载
挂载到emptyDir 挂载在如下目录,此目录是pod所在的node节点主机的目录,此目录下的data即对应容器里的/usr/share/nginx/html,实现目录挂载;图1红框里的号对应docker 的name中的编号,如下俩个图 apiVersion: apps/v1 k…...

类之间的比较
作者简介: zoro-1,目前大一,正在学习Java,数据结构等 作者主页: zoro-1的主页 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖 类之间的比较 固定需求式比较器 固定需求式 通过…...

设计模式之备忘录模式(Memento)的C++实现
1、备忘录模式的提出 在软件功能开发过程中,某些对象的状态在转换过程中,由于业务场景需要,要求对象能够回溯到对象之前某个点的状态。如果使用一些共有接口来让其他对象得到对象的状态,便会暴露对象的实现细节。备忘录模式是在不…...

学习笔记230804---restful风格的接口,delete的传参方式问题
如果后端提供的删除接口是restful风格,那么使用地址栏拼接的方式发送请求,数据放在主体中,后端接受不到,当然也还有一种可能,后端在这个接口的接参设置上是req.query接参。 问题描述 今天遇到的问题是,de…...

STM32使用IIC通信的引脚配置问题
STM32使用IIC通信的引脚配置问题 在使用IIC通信时,遇到引脚配置问题,记录一下: IIC的两个引脚SDA和SCL都要求既能输入又能输出。 问题: SDA线是由不同的器件分时控制的,这样就会有一个问题:当一个器件主动…...

题解 | #K.First Last# 2023牛客暑期多校10
K.First Last 签到题 题目大意 n n n 个人参加 m m m 场比赛,每场比赛中获得名次得概率均等 问针对某一人,他在所有场次比赛中都获得第一或倒数第一的概率 解题思路 如果人数 n > 1 n>1 n>1 ,每场比赛的概率是 p 2 n p\dfra…...

Python 程序设计入门(025)—— 使用 os 模块操作文件与目录
Python 程序设计入门(025)—— 使用 os 模块操作文件与目录 目录 Python 程序设计入门(025)—— 使用 os 模块操作文件与目录一、操作目录的常用函数1、os 模块提供的操作目录的函数2、os.path 模块提供的操作目录的函数 二、相对…...

excel逻辑函数篇1
1、AND(logical1,[logical2],…):用于测试所有条件是否均为TRUE 检查所有参数均为true,如果是则返回true 2、OR(logical1,[logical2],…):用于测试是否有为TRUE的条件 如果任意参数值为true,即返回true;只有当所有参数…...

前端基础(Vue的模块化开发)
目录 前言 响应式基础 ref reactive 学习成果展示 Vue项目搭建 总结 前言 前面学习了前端HMTL、CSS样式、JavaScript以及Vue框架的简单适用,接下来运用前面的基础继续学习Vue,运用前端模块化编程的思想。 响应式基础 ref reactive 关于ref和react…...

SystemVerilog interface使用说明
1. Interface概念 System Verilog中引入了接口定义,接口与module 等价的定义,是要在其他的接口、module中直接定义,不能写在块语句中,跟class是不同的。接口是将一组线捆绑起来,可以将接口传递给module。 2. 接口的优…...

机器人制作开源方案 | 送餐机器人
作者:赖志彩、曹柳洲、王恩开、李雪儿、杨玉凯 单位:华北科技学院 指导老师:张伟杰、罗建国 一、作品简介 1. 场景调研 1.1项目目的 近年来,全国多地疫情频发,且其传染性极高,食品接触是传播途径之一。…...

Gradio部署应用到服务器不能正常访问
用Gradio部署一个基于ChatGLM-6B的应用,发布到团队的服务器上(局域网,公网不能访问),我将gradio应用发布到服务器的9001端口 import gradio as gr with gr.Blocks() as demo:......demo.queue().launch(server_port90…...

数据暴涨时代,该如何数据治理?_光点科技
随着信息技术的迅猛发展,数据已经成为现代社会的核心资源。在这个被称为"数据暴涨时代"的时代里,大量的数据源源不断地被产生和积累,但如何有效地管理、分析和利用这些数据成为了一个迫切需要解决的问题。数据治理,作为…...

2021年03月 C/C++(三级)真题解析#中国电子学会#全国青少年软件编程等级考试
第1题:找和为K的两个元素 在一个长度为n(n < 1000)的整数序列中,判断是否存在某两个元素之和为k。 时间限制:1000 内存限制:65536 输入 第一行输入序列的长度n和k,用空格分开。 第二行输入序列中的n个整数ÿ…...

GPT-5出世?OpenAI GPT-5商标已注册
OpenAI的GPT已经成为了业界标杆,升级速度之快让人瞠目,别人追GPT-3.5的时候GPT-4横空出世,差距被拉开了,现在GPT-5就要来了。 据商标律师泄露的消息,OpenAI已于7月18日注册了GPT-5商标。虽然注册商标并不罕见…...

优雅的使用 Dockerfile 定制镜像
一、使用 Dockerfile 定制镜像 1.1、Dockerfile 定制镜像 镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,无法重复的问题、镜像构建透明性的问题、…...

limit的用法mysql
当你在 MySQL 数据库中使用 LIMIT 语句,它可以用于限制查询结果的行数。这在分页查询或者限制返回的数据量时非常有用。下面是一些示例: 返回前几行数据: SELECT * FROM Customers LIMIT 5;这将返回 Customers 表中的前 5 行数据。 分页查…...

clickhouse Checksum doesn‘t match: 问题修复
1. 问题描述 SQL 错误 [40] [07000]: Code: 40. DB::Exception: Checksum doesnt match: corrupted data. Reference: 50e8c1efa78de2881b725d44b04be1fe. Actual: 161c99eb681ec36b83540ecdd65ad8c9. Size of compressed block: 32846. The mismatch is caused by single bit…...

企业如何开展个人信息安全影响评估(PIA)二
基本概念 根据《信息安全 技术个人信息安全影响评估指南》(GB/T 39335—2020;personal information security impact assessment,简称“PIA”),个人信息安全影响评估是指针对个人信息处理活动,检验其合法合…...

android TextView 超出长度使用省略号
在Android中最常见的需求,就是在在外部展示信息时,需要简要展示内容。TextView仅需在静态布局文件中设置以下几个属性: android:maxWidth“100dp” // 宽度是多少才算超出 android:maxLines"2" // 高度多少才算超出 android:elli…...

c++ | 字节转换 | 字长 | 机器位数
为什么有的时候脑子转不过来?? 为什么要对字节、机器长啊、位啊都要门清 位数 一般的就是指计算机的位数,比如64位/32位,更简单的理解,计算机就是在不停的做二进制的计算,比如32位计算机,在长…...

7-4 交换最小值和最大值
分数 15 全屏浏览题目 切换布局 作者 C课程组 单位 浙江大学 本题要求编写程序,先将输入的一系列整数中的最小值与第一个数交换,然后将最大值与最后一个数交换,最后输出交换后的序列。 注意:题目保证最大和最小值都是唯一的。…...

解决Pycharm的Settings中Project不见了也无法选择Python Interpreter的方法
目录 一、问题如下二、解决方法 一、问题如下 突然打开项目没有python解释器,也无法重新配置python Interpreter,而且整个文件夹是黄色高亮的形式,如下显示,而且重新安装了pycharm也没用甚至说打开File–>Setting–>Projec…...

AWS EKS 集群自动扩容 Cluster Autoscaler
文章目录 一,需求工作需求说明 二,部署精简命令执行1,要求2,查看EC2 Auto Scaling groups Tag3,创建Serviceaccount需要的Policy,Role4,部署Cluster Autoscaler5,验证6,常…...

excel中有哪些通配符、excel配置问题,数学函数篇1之sum系列
学习excel前需要明确的是事: 在学习excel函数之前,大家需要明确一件事,excel现在设计到了一些新函数,这些新函数只能存在于office365、office2019及更 新版本之中,所以建议大家在学习时安装较新的版本,…...

工控行业需要熟悉的工业级通信协议
1. Modbus RTU Modbus RTU 是一种串行通信协议,常用于工控行业。它具有以下特点和优势: 采用二进制编码,数据传输更加高效。支持多种传输介质,如RS-232、RS-485等。容易实现和使用,适用于各种设备。具备强大的错误检…...

力扣题解(1030. 距离顺序排列矩阵单元格),带注释
题目描述 链接:点我 注意:多看几遍题目,开始没看懂…相当于计算矩阵网格里面的点(不要计算边界) 我开了题解才明白题的意思 orz… 题解 class Solution {public int[][] allCellsDistOrder(int rows, int cols, int rCenter, …...