Kotlin学习笔记(五):Kotlin中的高级特性

一、解构

Kotlin中使用operator关键字修饰函数,这样可以将一个函数标记为重载一个操作符或者实现一个约定。使用operator关键字修饰函数并且函数名只能为component1component2component3…时就是实现一个约定。

通过将该类实例赋值给一组变量,Kotlin可以直接将对应函数的值按照component1component2component3…的顺序赋值给该组变量,这个过程就叫"解构"。

class User(var age: Int, var name: String){

    operator fun component1() = age

    operator fun component2() = name

}

fun main(args: Array<String>) {
    val user = User(11, "Irving")
    //将该类实例赋值给一组变量
    val (age, name) = user
    
    println(age)
    println(name)
}

解构更常用的是在遍历一个map的时候,通过将map中的每一对键值对赋值给一组变量(key, value),从而可以同时遍历keyvalue

fun main(args: Array<String>) {
    val map = mapOf("key1" to "value1", "key2" to "value2")
    for((key, value) in map){
        println("$key --> $value")
    }
}

二、循环

Kotlin中的循环有以下几种形式

  1. 使用in关键字,in关键字后面为一个闭区间,表示从小到大遍历。

    for (i in 1..10){
        print("$i ")
    }
    

    结果:
    在这里插入图片描述

  2. 使用inuntil关键字,in关键字后面为一个左闭右开的区间。

    for (i in 1 until 10){
            print("$i ")
    }
    

    结果:
    在这里插入图片描述

  3. 使用indownTo关键字,in关键字后面为一个闭区间,表示从大到小遍历(Kotlin中不允许直接使用10..1这种方式从大到小遍历)。

    for (i in 10 downTo 1){
            print("$i ")
    }
    

    结果:
    在这里插入图片描述

  4. 使用setp关键字配合其他关键字使用,表示步长,默认setp为1。

    for (i in 1..10 step 2){
            print("$i ")
    }
    

    结果:
    在这里插入图片描述

  5. 使用repeat高阶函数,传入一个Lambda表达式。

    repeat(10){
        print("$it ")
    }
    

    结果:
    在这里插入图片描述
    查看repeat函数代码,本质上还是通过inuntil关键字实现的。

    @kotlin.internal.InlineOnly
    public inline fun repeat(times: Int, action: (Int) -> Unit){
        contract { callsInPlace(action) }
    
        for (index in 0 until times) {
            action(index)
        }
    }
    

三、集合操作符

Kotlin中可以通过集合操作符直接对集合进行操作,从而得到想要的结果。

  • map:对集合中的数据做改变,可以改变数据的类型。
  • filter:得到所有符合Lambda闭包中操作的数据。
  • find:得到符合Lambda闭包中操作的第一个数据。
  • findLast:得到符合Lambda闭包中操作的最后一个数据。
  • reduce:含有两个参数(集合中相邻的两个参数,用于遍历整个集合),对这两个参数进行操作,返回一个新参数,要求类型与集合中的参数类型相同。
  • ......
fun main(args: Array<String>) {
    val list = arrayListOf('a','b','c','d')

    val a = list.map {
    	//将集合中的Char类型转换为Int类型
        it - 'a'
    }.filter {
    	//得到所有大于0 数
        it > 0
    }.findLast {
    	//得到最后一个大于1的数
        it > 1
    }

    println(a)
}
自己定义集合操作符

Kotlin中可以通过给Iterable接口添加扩展函数来定义集合操作符,所有集合都可以直接调用自定义的集合操作符。

//定义一个集合操作符convert,作用类似于map
inline fun <T, E> Iterable<T>.convert(block: (T) -> E): MutableList<E>{
    val list = mutableListOf<E>()
    for (item: T in this) {
        list.add(block(item))
    }
    return list
}

fun main(args: Array<String>) {
    val list = arrayListOf('a', 'b', 'c', 'd')
    list.convert {
        it - 'a'
    }.forEach {
        print("$it ")
    }
}

四、作用域函数

Kotlin中的作用域函数和上面的集合操作符很类似,区别是Kotlin中所有的对象都可以调用作用域函数。

创建一个User对象:

data class User(var name: String)

fun main(args: Array<String>) {
    val user = User("Irving")
}
  1. let、run:letrun都会返回闭包的执行结果,区别是let有闭包参数,参数为执行闭包的这个对象,一般可以省略不写,用it代替。

    user.let {
        println(it.name)
        //最后一行返回闭包的执行结果
        "Hello World"
    }
    user.run {
        println(name)
        //最后一行返回闭包的执行结果
        "Hello World"
    }
    
  2. apply、also:applyalso都会返回执行该闭包的对象,区别是also有闭包参数,参数为执行闭包的这个对象,一般可以省略不写,用it代替。

    user.apply {
     	println(name)
    }.name//函数调用完返回执行该闭包的对象,所以可以继续调用该对象的属性
    user.also {
        println(it.name)
    }
    
  3. takeIf、takeUnless:takeIf的闭包返回一个判断结果,如果为falsetakeIf函数返回nulltakeUnlesstakeIf相反,为truetakeUnless函数返回null

    user.takeIf { it.name.isNotEmpty() }?.also { println(it.name) } ?: println("姓名为空")
        
    user.takeUnless { it.name.isEmpty() }?.also { println(it.name) } ?: println("姓名为空")
    
  4. with: with函数不是以扩展函数存在的,而是一个顶级函数。

    with(user){
       println(name)
        "test"
    }
    

    通过查看with函数的源代码,可以知道with函数相当于对接收到的对象进行传入的闭包操作。相当于在内部调用一次user.apply{},同时最后还能返回执行结果。

    public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        return receiver.block()
    }
    

你可能感兴趣的:(Kotlin学习笔记)