// 将lambda表达式移到最外面,省略小括号
cost {
val function = fibonacci()
for (i in 0…10) {
val longVal = function()
println(longVal)
}
}
}
===============================================================================
用inline关键字进行修饰,如果该函数接受一个匿名函数(lambda表达式),则可以使用inline关键字修饰改函数,然后接受的匿名函数会被编译器优化,内联到函数内部,会节省开销。
示例如下所示:
//内联函数
inline fun IntArray.forEatch(action:(Int)->Unit):Unit{
for(element in this) action(element)
}
//调用处
fun main(){
val ints = intArrayOf()
ints.forEach{
println(“hello$it”)
}
}
//实际编译之后的调用(大致)
fun main(){
val ints = intArrayOf()
for(element in this) {
println(“hello$element”)
}
}
上述所示,使用inline修饰之后,在编译期间kotlin会对代码调用栈进行优化。
示例如下所示:
inline fun cost(block:()->Unit){
val start = System.currentTimeMillis()
block()
println(System.currentTimeMillis() - start)
}
//调用
cost{
println(“hello”)
}
//实际编译效果
val start = System.currentTimeMillis()
println(“hello”)
println(System.currentTimeMillis() - start)
高阶函数内联
-
函数本身被内联到调用处
-
函数的函数参数被内联到调用处
-
public/protected的内敛方法只能访问对应类的public成员(也可以理解,毕竟可以在编译期间优化到调用处,怎么访问私有属性呢)
-
内联函数的内联函数参数不能被储存(赋值给变量)
-
内联函数的内联函数参数只能传递给其他内联函数参数
另: 与inline一块配合使用的有noinline以及crossinline。关于内联函数的详细说明,以及这个三个参数的详细区别,可参考:kotlin:inline、noinline、crossinline还傻傻分不清楚?看这一篇就够了
三、kotlin几个常用的高阶函数let、run、also、apply、use
==========================================================================================================
let源码如下所示:
public inline fun <T, R> T.let(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block(this)
}
注意:我们可以忽略掉contract契约检查(下面遇到的源码如包含contract,都可以进行忽略,且不在提及),那么核心的函数其实就是return block(this)
let : 将receiver作为参数传入block,并且返回block的返回值
简单使用实例如下所示:
val strLenght = arrayOf(“hello”, “world”).let {
it.joinToString(" ") { s: String ->
“$s length: ${s.length}”
}
}
println(strLenght)
//输出
hello length: 5 world length: 5
run源码如下所示:
public inline fun <T, R> T.run(block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
接收的block类型为T.() -> Unit 所以 block里面可使用this指代调用者
run : block里面可使用this指代调用者,并且返回block的返回值
简单使用实例如下所示:
val strLenght = arrayOf(“hello”, “world”).run {
this.joinToString(" ") { s: String ->
“$s length: ${s.length}”
}
}
println(strLenght)
//输出
hello length: 5 world length: 5
also源码如下所示:
public inline fun T.also(block: (T) -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block(this)
return this
}
和let的区别就是返回类型不一样了,block是无返回类型,整个函数返回调用者T
核心函数 block(this) return this
简单使用实例如下所示:
val arrayStr = arrayOf(“hello”, “world”).also {
val joinToString = it.joinToString(" ") { s: String ->
“$s length: ${s.length}”
}
println(joinToString)
}
println(arrayStr is Array)
//输出
hello length: 5 world length: 5
true
apply源码如下所示:
public inline fun T.apply(block: T.() -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
return this
}
和run的区别就是返回类型不一样了,block是无返回类型,整个函数返回调用者T
核心函数 block() return this
简单使用实例如下所示:
val arrayStr = arrayOf(“hello”, “world”).apply{
val joinToString = it.joinToString(" ") { s: String ->
“$s length: ${s.length}”
}
println(joinToString)
}
println(arrayStr is Array)
//输出
hello length: 5 world length: 5
true
use源码如下所示:
public inline fun <T : Closeable?, R> T.use(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
var exception: Throwable? = null
try {
return block(this)
} catch (e: Throwable) {
exception = e
throw e
} finally {
when {
apiVersionIsAtLeast(1, 1, 0) -> this.closeFinally(exception)
this == null -> {}
exception == null -> close()
else ->
try {
close()
} catch (closeException: Throwable) {
// cause.addSuppressed(closeException) // ignored here
}
}
}
}
核心代码就是try catch那一块,很明显,使用use函数自动帮我们处理了,异常以及资源的关闭。所以使用Closeable相关操作的时候,推荐使用use来进行资源管理
简单使用实例如下所示:
val datas = LinkedList<Pair<Char, Int>>()
File(“build.gradle.kts”).inputStream().reader().buffered().use {
var strLine = it.readLine()
while (strLine != “”) {
strLine.groupBy { char ->
char
}.map { map ->
map.key to map.value.size
}.run {
datas.addAll(this)
}
strLine = it.readLine()
}
}
println(datas.joinToString())
//输出
(p, 1), (l, 1), (u, 1), (g, 1), (i, 1), (n, 1), (s, 1), ( , 1), ({, 1), (/, 2), ( , 5), (i, 1), (d, 1), (‘, 2), (j, 1), (a, 2), (v, 1), (/, 2), ( , 7), (i, 4), (d, 1), (’, 4), (o, 3), (r, 3), (g, 1), (., 5), (j, 2), (e, 2), (t, 2), …展示内容有限,就不全部粘贴过来了
四、kotlin集合序列变换forEach、filter、map、flatmap、sum、reduce、fold
===========================================================================================================================
forEach,熟悉java的朋友相信都不陌生,且本系列文章在之前也多次用到forEach,下面我们就看看forEach具体是怎么操作的吧
forEach源码如下所示:
public inline fun Array.forEach(action: (T) -> Unit): Unit {
for (element in this) action(element)
}
很简单是不是,就是对集合元素进行了循环处理,调用了传进来的block
那按照惯例,也提供一个小demo
arrayOf(1,2,3,4).forEach {
print(it)
}
//输出
1234
filter,保留满足条件的元素
源码如下所示:
public inline fun Array.filter(predicate: (T) -> Boolean): List {
return filterTo(ArrayList(), predicate)
}
public inline fun <T, C : MutableCollection> Array.filterTo(destination: C, predicate: (T) -> Boolean): C {
for (element in this) if (predicate(element)) destination.add(element)
return destination
}
正所谓,知其然也要知其所以然。如上源码所示,filter的本质就是,循环判断block是否满足条件,如果满足则添加进入list,最后返回
简单使用如下:
arrayOf(1,2,3,4,5,6).filter {
it>3
}.joinToString ().let {
println(it)
}
//输出
4, 5, 6
map,集合中所有的元素一一映射到其他的元素构成新的集合
源码如下所示:
public inline fun <T, R> Array.map(transform: (T) -> R): List {
return mapTo(ArrayList(size), transform)
}
public inline fun <T, R, C : MutableCollection> Array.mapTo(destination: C, transform: (T) -> R): C {
for (item in this)
destination.add(transform(item))
return destination
}
分析发现,其实本质就是创建一个新的集合,加入传入map的函数的返回值而已
简单使用如下:
arrayOf(1,2,3,4,5,6).map {
“$it hello”
}.joinToString().let {
println(it)
}
//输出
1 hello, 2 hello, 3 hello, 4 hello, 5 hello, 6 hello
flatMap,集合中所有的元素一一映射到新集合并合并这些集合得到新集合
源码如下所示:
public inline fun <T, R> Array.flatMap(transform: (T) -> Iterable): List {
return flatMapTo(ArrayList(), transform)
}
public inline fun <T, R, C : MutableCollection> Array.flatMapTo(destination: C, transform: (T) -> Iterable): C {
for (element in this) {
val list = transform(element)
destination.addAll(list)
}
return destination
}
好多同学可能都对flatMap所要表达的意思,感到困惑难以理解,但是我们仔细分析一波源码,弄懂原理就简单很多了。
首先可以看到flatMap也是创建了新的ArrayList集合并且将函数重新传入到了flatMapTo的这个函数里了,这个时候我们注意,我们传入的函数的返回类型必须是可迭代的(Iterable类型)。
那我们在看flatMapTo干了什么事情,先是循环调用者的集合,然后调用函数,拿到我们传入的函数返回的集合,最后在addAll到信创建的ArrayList返回。
这么一说是不是就好理解flatMap的映射关系了,下面我们可以看一个demo
Demo如下所示:
arrayOf(1,2,3,4,5,6).flatMap {
val arrayList = ArrayList()
arrayList.add(it)
arrayList.add(1111)
arrayList
}.joinToString().let {
println(it)
}
//输出
1, 1111, 2, 1111, 3, 1111, 4, 1111, 5, 1111, 6, 1111
sum,所有元素求和
源码如下所示:
public fun Array.sum(): Int {
var sum: Int = 0
for (element in this) {
sum += element
}
return sum
}
较为简单,就不做说明了。
Demo所示如下:
println(arrayOf(1,2,3,4,5,6).sum())
//输出
21
reduce,将元素依次按规则聚合,结果与元素类型一致
源码如下所示:
public inline fun <S, T : S> Array.reduce(operation: (acc: S, T) -> S): S {
if (isEmpty())
throw UnsupportedOperationException(“Empty array can’t be reduced.”)
var accumulator: S = this[0]
for (index in 1…lastIndex) {
accumulator = operation(accumulator, this[index])
}
return accumulator
}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
总结:
各行各样都会淘汰一些能力差的,不仅仅是IT这个行业,所以,不要被程序猿是吃青春饭等等这类话题所吓倒,也不要觉得,找到一份工作,就享受安逸的生活,你在安逸的同时,别人正在奋力的向前跑,这样与别人的差距也就会越来越遥远,加油,希望,我们每一个人,成为更好的自己。
-
BAT大厂面试题、独家面试工具包,
-
资料包括 数据结构、Kotlin、计算机网络、Framework源码、数据结构与算法、小程序、NDK、Flutter
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
[外链图片转存中…(img-T7agn6VM-1712779809577)]
[外链图片转存中…(img-oTu7lj0x-1712779809578)]
[外链图片转存中…(img-eULVFMKU-1712779809578)]
[外链图片转存中…(img-jkfb8iZb-1712779809578)]
[外链图片转存中…(img-Sh5rrTPu-1712779809578)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
总结:
各行各样都会淘汰一些能力差的,不仅仅是IT这个行业,所以,不要被程序猿是吃青春饭等等这类话题所吓倒,也不要觉得,找到一份工作,就享受安逸的生活,你在安逸的同时,别人正在奋力的向前跑,这样与别人的差距也就会越来越遥远,加油,希望,我们每一个人,成为更好的自己。
-
BAT大厂面试题、独家面试工具包,
-
资料包括 数据结构、Kotlin、计算机网络、Framework源码、数据结构与算法、小程序、NDK、Flutter
[外链图片转存中…(img-xRjYl5sg-1712779809579)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!