我发现很多学过kotlin的人,迟迟不敢在项目中运用,主要是因为kotlin的 lambda与高阶函数没有学好。这2个东西往往是一起运用的。 网上很多类似的文章都讲的不够通透,导致大部分人都卡在这里。或者有一些人即使写了kotlin 但是也没用好lambda与高阶函数,导致kotlin的代码 全是java的味道。
大家可以用一下新版本的android studio,然后新建一个kotlin语言的loginActivity,如果里面的代码你能无障碍的基本看懂,那这篇文章就不用再看了,如果看起来障碍很大,那么建议你仔细看完这篇文章,之后再返回去看这个loginActivity的代码,相信结果是完全不一样的。
最后总结一下我的观点:想写好Kotlin的代码就看你对lambda与高阶函数理解的有多深,早期纠结那些晦涩的语法糖没有任何意义。
那这个func 又怎么理解呢?他为啥可以接受一个函数作为参数?
这里有人会问了,你咋知道 这个匿名函数是没有返回值的啊?
因为lambda表达式有一个特点,lambda括号里面的函数最后一行就是这个函数的返回值, 图中我们最后一行 是个print语句,这个print函数显然是没有返回值的,所以这个lambda 也就是这个匿名函数也就没有了返回值了。
然后我们反编译看一下这段代码
我们换个写法
我们再看一下反编译的:
下面我们再改进一下写法:
那当然还有终极的简写,也就是平常我们使用最多的写法:
很多人学不好lambda就是因为上来就看这个最简单的写法,而不知道这种写法是怎么来的。你搞清楚 这种写法的进化原因,自然就真正理解了lambda了。
来个更进一步 2个参数的
看下执行结果
实际上kotlin中的lambda 就是一个匿名函数,java8的lambda表达式 却是一个sam的语法糖
有了前面lambda 的铺垫,高阶函数 的理解就不难了。 下面给高阶函数下一个定义: 参数类型包含函数类型,或者返回值类型是一个函数类型 的函数 都可以称之为是高阶函数。
来看几个简单的高阶函数的例子:
看下源码:
再看个函数
然后我们看一下map函数的定义
所以你看高阶函数 也没什么难的,主要你能理解lambda 那么你就能理解好高阶函数
无非就是let run also apply use 这么5个,网上关于这几个函数的资料很多,但是介绍的我觉得都相当一般,这里我重新介绍一下 这几个函数对应的使用场景。 掌握了他们,可以说 理解kotlin的代码 就不会存在什么障碍了。
这里要着重说明的是,其实run函数和apply函数 并没啥大作用。平时自己写 主要还是let also 和use
看一段代码,看看let和also的区别
最后一个use操作符,是个人最爱的一个操作符,因为这东西真的省事。我演示一遍你就知道他有多省事了!
最后用一张图来总结:
我们平时开发业务代码时 其实最主要的工作就是对一个集合进行增删改查,过滤啊 之类的操作。 kotlin中 提供了大量对集合操作的 高阶函数,理解好他们 对你读代码或者是写代码的操作都是非常非常有帮助的。
前面的代码中我们已经演示过了for each循环的用法 这里补充一点,foreach函数是可以提前跳出的。
当然上面的写法一般是不推荐的,因为确实很迷惑人。 有更高级的函数 可以满足你对集合的要求。
看下图:
看个例子:
有时候我们对一个集合的操作,可能不止一个函数,需要多个函数协同操作,这个时候有更方便的 写法。
有人要问了,这个asSeq不调用 是啥效果?我们可以看一下
再看一个例子
看下flatmap
先看一张图 了解一下主要的聚合操作
看下fold的使用
其余的2个高阶函数就不再演示了。大家用到的时候自行查阅api即可。
前面已经学完了lambda和大部分高阶函数,这里我们组合一下他们的用法,重新将知识串起来。
1.统计一个文件里 除了空格字符以外,每个字符出现的次数(尽量只使用lambda)
/** * 1.读文件 然后把文件的内容 转成char的数组 * 2.过滤数组,空格符直接忽略 * 3.用groupBy 来将整个数组 重新分组(分组的结果是一个map), key就是出现的字符,value就是出现的全部字符 * 4.用map操作符 再将这个map 拍平成一个list,这个list的 内容形如:e 出现次数: 21 * 5.用let操作符 将结果打印出来即可 */ fun main() { File("/Users/wuyue/IdeaProjects/KotlinTest/src/enumTest.kt").readText().toCharArray().filterNot { it.isWhitespace() }.groupBy { it }.map { it.key + " 出现次数: " + it.value.size }.let { println(it) } } 复制代码