网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
说明仅仅是返回了nonLocalReturn函数,main函数还是往下走了
**crossinline关键字**
绝大多数高阶函数都可以声明为内联函数,但是也有例外的情况。如下列代码:
inline fun Runnable(block:() -> Unit):Runnable{
return object:Runnbale {
override fun run(){
block()
}
}
}
这个时候idea会提示block()调用错误,这是因为有可能存在不合法的non-local return,block()的调用处与定义处不在一个调用上下文。
那么如何解决这个问呢?
使用crossinline关键字修饰传递的函数就可以使它在Lambda表达式中一定不return,而且`crossinline`修饰除了不return之外,其他内联函数的属性都是一样的。
**三、几个常用的高阶函数**
**let函数**
let函数调用一般是针对一个定义在特定情况下使用的变量,例如我们可以避免对变量的null判断。观察如下代码:
// any 不为null 时才会调用let 函数
any?.let {
//it 就是代表any对象
// todo()方法就是any对象的方法
// it.todo()的返回值作为let函数的返回值返回
it.todo()
}
在Android开发中的实际场景就是我们可能要对一个变量进行多次判空才调用,如:
mTextView?.text = “Kotlin”
mTextView?.textSize = 16f
使用let函数后可以简写为
mTextView?.let{
it.text = “Kotlin”
it.textSize = 16f
}
**run函数**
run函数其实就是let函数的升级版,run函数接受一个lambda 函数为参数,传入this并以闭包形式返回,返回值是最后的计算结果,那么上述的代码可以优化成下面这样:
mTextView?.run{
text = “Kotlin”
textSize = 16f
}
**apply函数**
apply函数和run函数的结构模式很相像,但是apply函数返回的是调用对象本身,因为apply函数的这个特性,所以它特别有助于我们进行多级的判null行为。下面我们通过一个代码示例了解一下:
apply函数的一般结构:
val applyRes = any.apply{
//todo()是 any 对象的共有属性或方法
todo()
// 最后返回的是any对象,而不是2
1+1
}
apply的简单应用举例:
//定义了一个公司对象 包含部门和人员名字
class Company(var department:Department? = null){
class Department(var departmentName: String? = null,var person:Person? = null){
class Person(var name:String? = null)
}
}
fun main() {
val company:Company? = Company(Company.Department(“一部”, Company.Department.Person(“Jeremy”)))
company?.department?.apply {
departmentName = “二部”
}?.person?.name.also {
println(“这个
c
o
m
p
a
n
y
?
.
d
e
p
a
r
t
m
e
n
t
?
.
d
e
p
a
r
t
m
e
n
t
N
a
m
e
的员工是
{company?.department?.departmentName}的员工是
company?.department?.departmentName的员工是it”)
}
}
打印的信息是:这个二部的员工是Jeremy
**also函数**
上述的apply应用举例中,我们最后调用了also函数,这个函数的作用和let函数是类似的,其中it就是返回的调用对象本身,其一般的结构格式就是:
val alsoRes = any.also {
//it代表的就是any todo是any的属性方法
it.todo()
1+1 //返回的是any对象,而不是2
}
**use函数**
use函数最大的一个特征就是会自动关闭调用者,无论其中间是否出现异常,因为use函数内部实现也是通过try-catch-finally块捕捉的方式,而close操作在finally里面执行,所以无论是正常结束还是出现异常,都能正确关闭调用者。
怎么才能调用use函数呢?
凡是实现了Closeable接口的对象都可以调用use函数。
因为use函数使得Kotlin中对File对象和IO流操作变得行云流水。
File(“build.gradle”).inputStream().reader().buffered()
.use {
print(it.readLines())
**四、集合变换序列**
**4.1、filter操作**
filter的操作是保留满足条件的元素得到新的列表,观察下列代码:
val arr = intArrayOf(1,2,3,4)
//asSequence()转换成懒序列
val arrFilter = arr.asSequence().filter { it%2 == 0 }
val arrFilter = arr.filter { it%2 == 0 }
for (e in arrFilter){
println(e)
}
打印的数据:
2
4
**4.2、map变换**
map变换就是一种映射一一对应的操作:
val list: MutableList = mutableListOf(1, 2, 3, 4)
val listMap = list.map { it*2 + 1}
for (e in listMap){
println(e)
}
打印的数据是:
3
5
7
9
集合的每个数据对应执行lamba表达式中的it*2 + 1返回一个新的数据集合
下面我们看一下filter和map结合的使用
懒序列调用法:
val list: MutableList = mutableListOf(1, 2, 3, 4)
list.asSequence().filter {
println(“filter $it”)
it % 2 ==0
}.map {
println(“map $it”)
it*2 + 1
}.forEach {
println(“forEach $it”)
}
打印结果:
filter 1
filter 2
map 2
forEach 5
filter 3
filter 4
map 4
forEach 9
上述看到打印结果是主要有符合条件的都会先往下走,**懒序列有一个很重要的点就是forEach是一个阀门作用,如果把forEach去掉就不会执行前面filter和map的操作,这就是懒序列的意义,当你需要的时候才会执行**。那我们看一下饿汉式的调用结果:
val list: MutableList = mutableListOf(1, 2, 3, 4)
list.filter {
println(“filter $it”)
it % 2 ==0
}.map {
println(“map $it”)
it*2 + 1
}.forEach {
println(“forEach $it”)
}
打印结果:
filter 1
filter 2
filter 3
filter 4
map 2
map 4
forEach 5
forEach 9
可以看到它无论是否符合条件,都会先执行完再进行下一步操作。
**4.3、flatMap变换**
flatMap就是把集合的元素映射成集合,每个元素对应一个新的集合,最后把这些集合组成一个最终的新的集合。如下面代码:
val list: MutableList = mutableListOf(1, 2, 3, 4)
list.flatMap { 0 until it }.joinToString().let(::println)
打印结果
0, 0, 1, 0, 1, 2, 0, 1, 2, 3
即是每个元素依次对应的集合是:
0 -> 0
1 -> 0,1
2 -> 0,1,2
3 -> 0,1,2,3
flatMap的返回值只有是Iterable即可,如下:
val list: MutableList = mutableListOf(1, 2, 3, 4)
val listFlatMap = list.flatMap { listOf(it+1) }
for (e in listFlatMap){
println(e)
}
打印结果:
2
3
4
5
**4.4、集合的聚合操作举例**
**sum:所有元素求和。**
**reduce:将元素依次按规则聚合,结果与元素类型一致。**
**fold:给定初始化值,将元素按规则聚合,结果与初始化值类型一致。**
其中reduce其实就是fold的简化版,我们简单看一下fold函数的操作:
val list: MutableList = mutableListOf(1, 2, 3, 4)
val strFold = list.fold(StringBuffer()){
//acc就是上次拼接的结果
acc, i -> acc.append(i)
}
println(strFold)
打印结果:
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
[外链图片转存中…(img-kv6As8Cq-1715895567704)]
[外链图片转存中…(img-89KDKLcL-1715895567704)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新