kotlin复习提高篇Day03 2020.7.25

本文深入探讨Kotlin中集合的初始化与操作,包括List、Set、Map的不同使用方式,lambda表达式的定义与简化,以及集合中常用的函数式API如map、filter、any和all的应用。同时,讲解了Kotlin如何处理空指针问题,提供多种判空工具。

一.集合

传统意义上的集合是List和Set,再广泛一点的话也要加上Map。其实现类分别为
ArrayList、LinkedList,HsahSet,HashMap

①传统的初始化集合的方式为

fun main() {
    val list = ArrayList<String>()
    list.add("Apple")
    list.add("Banana")
    list.add("Orange")
    list.add("Pear")
    list.add("Grape")

    for(fruit in list){
        println(fruit)
    }
}

②listOf

这是Java方式,这种方式比较繁琐,为此Kotlin专门提供了一个内置的listOf函数来简化初始化集合的写法

fun main() {
    val list = listOf("Apple","Banana","Orange","Pear")
    for(fruit in list){
        println(fruit)
    }
}

③mutableListOf

不过listOf()函数创建的是一个不可变的集合(思想和val关键字,类默认不可继承初衷是类似的),不可变的集合只能用于读取,无法对集合进行添加、修改或删除。如果想让其变成可变的集合,改为**mutableListOf()**即可

fun main() {
    val list = mutableListOf("Apple","Banana","Orange","Pear")
    list.add("1")
    for(fruit in list){
        println(fruit)
    }
}

Set也是有setOf和mutableSetOf。不过需要注意的是,Set底层是使用hash映射机制来存放数据的,因此集合中的元素无法保证有序,这是和List集合最大的不同之处

④Map

传统的Map

fun main() {
    val map = HashMap<String,Int>()
    map.put("Apple",1)
    map.put("Banana",2)
    map.put("Orange",3)
}

不过kotlin并不建议用put或者get,而是建议使用类似于数组下标的语法结构

fun main() {
    val map = HashMap<String,Int>()
    map["Apple"] = 1
    map["Banana"] = 2
    map["Orange"] = 3
}

类似于list和set,map也有mapOf和mutableMapOf,写出来更简单

fun main() {
    val map = mapOf("Apple" to 1,"Banana" to 2,"Orange" to 3)
    for((fruit,number) in map){
        println("fruit is  "+ fruit + "  number is  "+number)
    }
}

二.lambda表达式

①lambda定义

lambda就是一小段可以作为参数传递的代码,这个很厉害,因为我们一般传递参数的时候都只是传递变量,而借助lambda却允许传入一小段代码(虽然代码数量没有限制,但是不建议传太多,否则会影响代码的可读性)

②lambda表达式的语法结构

{参数名1:参数类型,参数名2:参数类型 -> 函数体}
最外层是一对大括号,参数列表的结尾使用一个->符号,表示参数列表的结束以及函数体的开始,函数体中可以编写任意行代码(当然不建议写太多),并且最后一行代码会自动作为lambda表达式的返回值
实际在应用过程中,我们一般都是用的简化版写法

③lambda表达式的简化过程

(1)原版是这样的

fun main() {
    val list = listOf("Apple","Banananana","Orange")
    val lambda = { fruit: String ->fruit.length}
    val maxLengthFruit = list.maxBy(lambda)

    println(maxLengthFruit)
}

(2)首先lambda变量根本无需定义,然后kotlin规定当lambda参数是函数的最后一个参数时,可以将lambda表达式移到函数括号的外面

fun main() {
    val list = listOf("Apple","Banananana","Orange")
    val maxLengthFruit = list.maxBy(){ fruit: String ->fruit.length}

    println(maxLengthFruit)
}

(3)如果lambda参数是函数的唯一一个参数的话,还可以将函数的括号省略

fun main() {
    val list = listOf("Apple","Banananana","Orange")
    val maxLengthFruit = list.maxBy{ fruit: String ->fruit.length}

    println(maxLengthFruit)
}

(4)最后,由于kotlin拥有出色的类型推导机制,所以lambda表达式中的参数列表其实在大多数情况下不必声明参数类型

fun main() {
    val list = listOf("Apple","Banananana","Orange")
    val maxLengthFruit = list.maxBy{ fruit ->fruit.length}

    println(maxLengthFruit)
}

(5)最后,当lambda表达式的参数列表中只有一个参数时,也不必声明参数名,而是可以使用it关键字来代替

fun main() {
    val list = listOf("Apple","Banananana","Orange")
    val maxLengthFruit = list.maxBy{ it.length}

    println(maxLengthFruit)
}

这就是简化过程的完整版了

三.集合中几个比较常用的函数式API

①map函数

集合中的map函数是最常用的一种函数式API,它用于将集合中的每个元素都映射成一个另外的值,比如将所有的水果都变成大写

fun main() {
    val list = listOf("Apple","Banananana","Orange")
    val list1 = list.map{ it.toUpperCase()}
    for(newFruit in list1){
        println(newFruit)
    }

}

②filter函数

是用来过滤集合中的数据的。它既可以单独使用,也可以配合刚才的map函数一起使用

fun main() {
    val list = listOf("Apple","Banananana","Orange")
    val list1 = list.filter { it.length<= 6 }.map{ it.toUpperCase()}

    for(fruit in list1){
        println(fruit)
    }
}
/*
APPLE
ORANGE

 */

这里就是将字母长度小于等于6的水果转化为大写,注意,虽然这里filter和map函数互换位置后仍可以实现,但是效率会降低,因为先用map,会先遍历所有的元素。

③any和all

any用于判断集合中是否至少存在一个元素满足指定条件,all函数用于判断集合中是否所有函数都满足指定条件

fun main() {
    val list = listOf("Apple","Banananana","Orange")
    val result1 = list.any { it.length <= 5 }
    val result2 = list.all { it.length <= 5 }
    println(result1)
    println(result2)

}
/*
true
false
 */

④Java函数式API的使用

使用条件:如果我们在kotlin代码中调用了一个Java方法,并且该方法接收一个Java单抽象方法接口参数,就可以使用函数式API
Java单抽象方法接口指的是接口中只有一个待实现方法,如果接口中有多个待实现方法,则无法使用函数式API

比如Runnable接口

interface Runnable{
    void run();
}

按照前面说的,对于任何一个Java方法,只要它接收Runnable参数,就可以使用函数式API
Java版本

    public static void main(String[] args) {
        new Thread(new Runnable(){
            @Override
            public void run() {
                System.out.println("run");
            }
        }).start();
    }

kotlin版本(未简化的)

fun main() {
    Thread(object: Runnable{
        override fun run() {
            println("run")
        }
    }).start()
}

简化后,就可以变成

fun main() {
    Thread{
          println("run")
        }.start()
}

我理解为省略了接口名和接口的唯一待实现函数名,直接写函数体

四.空指针检查

①可空类型系统

kotlin默认所有的参数和变量都不可为空,将空指针异常的检查提前到了编译时期。
可为空的类型系统就是在类名的后面加上一个问号,比如Int? String?

class Study(){
    fun doLearn(){}
    fun doRead(){}
}

fun main() {
  doStudy(null)
}

fun doStudy(study: Study?){
    if(study != null) {
        study.doLearn()
        study.doRead()
    }
}

②判空辅助工具

(1)?.

当对象不为空时正常调用相应的方法,当对象为空时则什么都不做

比如

if(a != null){
    a.doSomething()
}

可以简化为

a?.doSomething()
(2)?:

这个操作符的左右两边都接收一个表达式,如果左边表达式的结果不为空就返回左边表达式的结果,否则就返回右边表达式的结果

比如

val a = if(study != null){
    study
}else{
    0
}

可以改为

val a = study ?: 0
(3)!!

!!是非空断言工具,意在表示这里的对象一定不为空,这是一种有风险的写法

(4)let函数

这个函数提供了函数式API的编程接口,并将原始调用对象作为参数传递到Lambda表达式中

fun doStudy(study: Study?){
        study?.doLearn()
        study?.doRead()
}

上面这种写法是比较啰嗦的,如果使用let,就会简化

fun doStudy(study: Study?){
        study?.let { 
            it.doRead()
            it.doLearn()
        }
}
2025-06-19 08:32:56 FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:checkReleaseDuplicateClasses'. > 1 exception was raised by workers: java.lang.RuntimeException: Duplicate class kotlin.ArrayIntrinsicsKt found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.BuilderInference found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.Deprecated found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.DeprecationLevel found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.DslMarker found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.ExceptionsKt found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.ExceptionsKt__ExceptionsKt found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.Experimental found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.Experimental$Level found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.ExperimentalMultiplatform found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.ExperimentalStdlibApi found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.ExperimentalUnsignedTypes found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.ExtensionFunctionType found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.Function found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.HashCodeKt found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.InitializedLazyImpl found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.KotlinNullPointerException found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.KotlinVersion found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.KotlinVersion$Companion found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.LateinitKt found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.Lazy found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.LazyKt found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.LazyKt$WhenMappings found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdlib-1.5.31.jar (org.jetbrains.kotlin:kotlin-stdlib:1.5.31) Duplicate class kotlin.LazyKt__LazyJVMKt found in modules jetified-kotlin-stdlib-1.3.50.jar (kotlin-stdlib-1.3.50.jar) and jetified-kotlin-stdli
06-20
### Kotlin 标准库版本冲突解决方案 当项目中存在多个不同版本的 `kotlin-stdlib` 时,可能会导致重复类冲突的问题。例如,`Duplicate class kotlin.jdk7.AutoCloseableKt found in modules kotlin-stdlib-1.8.20 (org.jetbrains.kotlin:kotlin-stdlib:1.8.20)` 这样的错误表明某些模块依赖了不同的 Kotlin 标准库版本[^2]。 为了解决此类问题,可以采取以下方法: #### 方法一:使用 `kotlin-bom` 通过引入 `kotlin-bom`(Bill of Materials),可以统一管理所有 Kotlin 相关依赖的版本。在 `build.gradle` 文件中添加以下内容: ```gradle implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.0")) ``` 这将确保所有 Kotlin 标准库依赖使用相同的版本,从而避免冲突[^2]。 #### 方法二:强制指定标准库版本 如果项目中存在多个版本的 `kotlin-stdlib`,可以通过 `resolutionStrategy` 强制指定一个版本。在 `build.gradle` 中添加以下代码: ```gradle configurations.all { resolutionStrategy.eachDependency { DependencyResolveDetails details -> if (details.requested.group == 'org.jetbrains.kotlin') { details.useVersion "1.5.31" // 指定统一的版本号 } } } ``` 这种方法可以确保所有 Kotlin 标准库依赖都使用指定的版本,从而避免重复类的问题[^4]。 #### 方法三:检查并清理冗余依赖 有时候,项目的依赖树中可能存在不必要的冗余依赖。可以运行以下命令来查看依赖树,并手动移除不需要的依赖: ```bash ./gradlew app:dependencies ``` 根据输出结果,找到冲突的依赖项,并在 `build.gradle` 文件中显式排除冗余依赖。例如: ```gradle implementation('some-library') { exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib' } ``` #### 方法四:更新 Gradle 和 Kotlin 插件 确保使用的 Gradle 和 Kotlin 插件版本是最新的,或者至少与项目中的 Kotlin 标准库版本兼容。如果遇到类似 `Could not find org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31-release-542` 的问题,可能需要声明额外的仓库[^3]。例如,在 `settings.gradle` 或 `build.gradle` 文件中添加以下内容: ```gradle repositories { mavenCentral() google() maven { url 'https://maven.aliyun.com/repository/public' } } ``` ### 示例代码 以下是一个完整的 `build.gradle` 配置示例,结合了上述方法: ```gradle plugins { id 'org.jetbrains.kotlin.android' version '1.5.31' apply false } repositories { mavenCentral() google() maven { url 'https://maven.aliyun.com/repository/public' } } dependencies { implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.5.31")) implementation("org.jetbrains.kotlin:kotlin-stdlib:1.5.31") } configurations.all { resolutionStrategy.eachDependency { DependencyResolveDetails details -> if (details.requested.group == 'org.jetbrains.kotlin') { details.useVersion "1.5.31" } } } ``` ### 注意事项 - 如果仍然无法解决问题,可以尝试关闭 Gradle 的离线模式。 - 确保所有团队成员使用相同的依赖版本,以避免因环境差异导致的问题。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值