kotlin复习提高篇Day03 2020.7.25

一.集合

传统意义上的集合是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()
        }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值