Kotlin 基础语法-04-高级特性

本文主要写kotlin中的解构、循环和集合操作符、 运算符重载、 作用域函数、 中缀表达式、DSL相关知识来展开。

  1. 解构
fun main(args: Array<String>){
     
    val user = User(28,"samuelnotes")

    val (age,name) = user
    /// 这个赋值过程是 age = user.component1()、 同理 name = user.component2()

    println("$age , $name")

}

 class User(var age : Int,  var name : String){
    // 名字是 component+ 数字 
    operator fun component1()= age
    operator fun component2()= name

}

operator : 将一个函数标记为重载一个操作符或者实现一个约定、
解构就是将一个对象、拆解给不同的变量、同时赋值、
再来个例子:

val map:Map<String,String> = mapOf<String,String>("key" to "value", "value" to "value2")

    for((k : String, v: String) in map){

        println("$k == $v")

    }

打印结果当然就是

key == value
value == value2
  1. kotlin循环

我们想一下java中的循环怎么来着?

for (int i = 0 ; i< 10 ; i++){
    // ... 
}

当然这在kotlin中是不允许的。

/// 这个遍历包含10
    for(i : Int in 1..10){

        println("$i")
    }

    println("++++++++++++++++")
    /// .. 的左边只能小于等于右边、所以10..1之间是没有区间的。打印不出什么东西。 
    for(i  in 10 .. 1){

        println("$i")
    }

    println("++++++++++++++++")


    for(i  in 10 downTo  1){

        println("$i")
    }

    println("++++++++++++++++")

    for(i  in 10 downTo  1 step 2){

        println("$i")
    }

    println("++++++++++++++++")


    for(i  in 1 until 10){

        println("$i")
    }

    println("++++++++++++++++")

    for(i  in 1 until 10 step 2){

        println("$i")
    }

    println("++++++++++++++++")


    for(i  in 1 .. 10 step 3){

        println("$i")
    }

    println("++++++++++++++++")

    var list =  arrayListOf<String>("a","b","c","d")
    // 读取元素、 遍历 没什么好说 、和java中基本一样 
    for(str in list){
        println("$str")
    }

    println("++++++++++++++++")
    // 这个是包含索引的
    for((i , v) in list.withIndex()){
        println("index $i, val is $v")
    }

    println("++++++++++++++++")

    /// 高阶函数中的闭包、 重复10次 、循环执行10次
    repeat(10,{

        println("$it")
    })
  1. 集合操作符

类似于RxJava 中的操作符,

fun main(args: Array<String>){


    mapfilterfind()

}

fun mapfilterfind() {

    val list = arrayListOf<Char>('a','b','c','d','e')

    val filtered =
    /// 对每一个元素都进行 map 之后 闭包的操作、 
    list.map { it - 'a' }
    /// 过滤 int类型 >0 的所有元素
            .filter { it >0 }
            /// 返回复合闭包数据的第一个元素 、如果需要最后一个元素 还有findLast 
            .find { it > 1 }

    println(filtered)
}

注释很清楚了、不再赘述、 我们继续前进。
打印结果:

2

再来个例子:

fun filterTestCase() {

    val a : Array<String> = arrayOf("4","5","7","i","f","w","0","8")

    val index : Array<Int> = arrayOf(5,3,9,4,8,3,1,9,2,1,7)

    index.filter { it < a.size }
            /// 过滤小于数组大小的数字
            .map {
                a[it]
            }
            // 合并
            .reduce { l, r ->

                "$l$r"

            }
            // 最终结果, 相当于Rxjava中的订阅方法
            .also {
            println("pwd: $it")
    }

}

上述代码不再赘述、注释很清楚。
打印结果:

pwd: wifi5758

再来个demo

fun converListType() {

 val   list : List<Int> = listOf(1,2,3,4,5)
    list.convert { it + 1 }
            .forEach { println("$it") }


}

/**
 * 传入闭包
 * 从类型T list 转换成类型E list
 */
inline fun<T,E> Iterable<T>.convert(aciton:(T)->(E)):MutableList<E>{
    /// 声明list
    val list:MutableList<E> = mutableListOf()
    /// action闭包执行结果通过add 添加到list 中
    for(item : T in this) list.add(aciton(item))
    return list
}

注释很清楚、不再赘述,
看一下打印结果是不是每个元素都进行+1 操纵

2
3
4
5
6
  1. 作用域函数

如果用习惯了集合操作符、突然你会想有没有一种东西或者工具能够操作对象、或者其他数据类型数据呢? 答案是、作用域函数。

在kotlin中常用的作用域函数有

run{...}
with(T){...}
let{...}
apply{...}
also{...}
...

一一来看吧、 单一解释太费劲、我们只需要了解常见的几种和实现原理、 来一段代码快速带过、

/**
 * Created by samuelnote on 2020/1/5.
 * 作用域函数
 */
fun  main(args: Array<String>){


    val user= Child("jerry",10)

//    val letResult = user.let { user->"let::${user.javaClass.simpleName}" }
    val letResult = user.let { "let::${it.javaClass.simpleName}" }

    println(letResult)

    val runResult = user.run { "run::${this.javaClass.simpleName}" }

    println(runResult)
    /// 简单写一下 、 let / run  都能返回闭包的执行结果、 let 、与run 没有本质的区别、只是run 不能够传递参数、 而let 是可以传递参数的、 在run中this代表的就是user 调用run闭包的对象、

    val also = user.also { user->
       println( "also::${user.javaClass}")
    }.apply {
        println(  "apply::${this.javaClass}")
        this.name= "samuelnotes"
    }.apply {
        this.age = 0
    }

    println(also)

     简单写一下、 also 和 apply 不返回执行结果、只返回调用对象、 所以都可以实现链式调用、 可以一直. 下去、 而also与apply 的区别是 also 有闭包参数、 而apply  没有闭包参数。


    /// 这个闭包返回一个boolean 类型的值、 如果闭包为false 、则返回值为空、 返回非空对象、
     user.takeIf { it.age >=0 }?.also { println("name is : ${it.name} age is : ${it.age}") }?: println(user)

    // 这个闭包返回的结果与执行逻辑与take if 相反、 如果闭包内容返回false 则返回非空对象、 否则返回空、 执行后边的打印程序
    user.takeUnless { it.age<0 }?.also { println("name is : ${it.name} age is : ${it.age}") }?: println(user)


     重复执行num 次闭包
    repeat(10,{

        println("$it"+user.name)

    })

    /// with 比较特殊、 前边都是扩展函数、而with是顶函数

    with(user){

        this.name= "jack"
    }

    /**
     * Calls the specified function [block] with the given [receiver] as its receiver and returns its result.
     */
//    @kotlin.internal.InlineOnly
//    public inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
    /// 就是类似于 user.apply{this.name = "rose"}
//

}

/**
 * 用户信息数据类
 */
data class Child(var name : String , var age : Int)

集合操作符实现原理其实就是作用域函数、 来看几个

/**
    遍历 
    */
   @kotlin.internal.HidesMembers
    public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
      for (element in this) action(element)
   }
   
   /**
 * 传入闭包
 * 从类型T list 转换成类型E list
 */
inline fun<T,E> Iterable<T>.convert(aciton:(T)->(E)):MutableList<E>{
    /// 声明list
    val list:MutableList<E> = mutableListOf()
    /// action闭包执行结果通过add 添加到list 中
    for(item : T in this) list.add(aciton(item))
    return list
}

看完之后是不是很提神、我靠、原来是这样的。

当然常用的操作符不止这么几个、还有很多
类似、

<!--元素操作类 -->
contains
elementAt
firstOrNull
lastOrNull
indexOf
singleOrNull  返回符合条件的单个元素、如果没有或者超过一个 则返回null  

<!--判断类-->

any   是否有满足条件的? 是则true 
all    是否都满足条件
none   是否都不满足条件、 是则返回true
count  满足条件的个数
reduce   从第一项到最后一项累积

<!--过滤类-->

filter 过滤掉所有满足条件的元素 

filterNot  过滤所有不满足条件的元素

filterNotNull  过滤Null

take  返回前N个元素

<!--转换类-->

map  转换成另一个元素 、 

mapIndexed  除了转换成另一个集合,还可以拿到Index

mapNotNull  执行转换前过滤掉为Null的元素

flatMap  自定义逻辑合并两个集合 

groupBy  按照某个条件分组 返回Map

<!--排序类-->

reversed  

sorted 

sortedBy  自定义排序

sortedDescending

如果有一定的语言基础这些操作符只看名字就知道什么意思了吧、 注释很清楚了、如果还有不清楚的、我们讨论共同学习、

  1. 总结

时间原因, 运算符重载和中缀表达式 DSL 放在下篇文章,

多上手敲、多尝试、多思考、 有问题评论区我们共同讨论进步。