• kotlin-高级特性一


    解构

    fun main(args : Array<String>){
    	val user = User(12,"name")
    	val (age,name) = user
    	println(age)
    	println(name)
    }
    
    calss User(var age:Int,var name:String){
    	//component 是固定写法,在后面跟的数字,表示对应结构体的第几个变量
    	operator fun component1() = age 
    	operator fun component2() = name
    }
    
    operator : 将一个函数标记为重载一个操作符或者实现一个约定
    
    应用场景:在遍历一个map集合的时候可以使用解构,可以同时获取到key 和 vul, 例如下
    val map:Map<String,String> =mapOf<String,String>{"key" to "key","vul" to "vul"}
    for((k,v) in map){
    	println("key=$key  vul=$vul")
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    循环与集合操作符

    循环
    
    var count:Int
    for(count = 0; count < 10; count++){
    	//....
    }
    
    上述类似java的for循环,在kotlin 中是没有的。但kotlin 提供了更强大的。如下
    //i变量,用于迭代  1..10 表示从1-10的一个区间
    for(i in 1..10){
    	println(i)
    }
    //上述 ..区间 最后会被until 这个函数重写
    for(i in 1 until 10){
    	println(i)
    }
    // downTo 函数表示递减 从10到1递减
    for(i in 10 downTo 1){
    	println(i)
    }
    //setp 函数表示步径 每次增幅为2 
    for(i in 1..10 setp 2){
    	println(i)
    	//println 输出结果:1 3 5 7 9
    }
    //kotlin 自定义的一个高阶函数 闭包中it 是一个计数器,表示循环到第几步了
    //重复执行当前闭包
    repeat(10){
    	println(it)
    }
    
    val list : ArrayList<String> =arrayListOf<String>{"a","b"}
    for(str in list){
    	println(str)
    }
    //使用map 是可以直接通过结构拿到key,vul。而list需要调用withIndex 才可以拿到index
    for((index,str) in list.withIndex()){
    	println("第${index}个元素是 $str")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    kotlin 集合操作符

    val list =arrayListOf<Char>{'a','b','c'}
    //.map 操作符可以将
    val a = list.map {it - 'a'}
    		.filter {it > 0} //过滤
    		.find {it > 1} //查找第一个匹配的结果
    
    fun main(args:Array<String>){
    	val a : Array<String> = arrayOf("4","0","h","d")
    	val index : Array<String> = arrayOf(0,4,5,7,8,3,6)
    	
    	index.filter{//取a.size 长度的 index 元素
    		it < a.size
    	}.map{//将传入的it ,返回为一个string
    		a[it]
    	}.reduce{s,s1 -> //将两个值合并
    		"$s$s1"
    	}.also{//最终结果
    		println("$it")
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    kotlin 自定义集合操作符

    其实kotlin 的所有操作符,都是以inline (内联函数)的扩展函数来实现的。例如下

    //将输入的T类型 转换为E类型
    inline fun <T,E> Iterable<T>.convert(action:(T) -> (E)):Iterable<E>{
    	val list:MutableList<E> =mutableListOf()
    	for(item:T in this) list.add(action(item))
    	return list
    }
    
    fun myQeperator(){
    	val list: List<Int> =listOf(1,2,3,4,5)
    	list.convert{
    		it+1
    	}.forEach{
    		println(it)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    作用域函数

    是kotlin 内置的一系列可以对数据做一个变换的函数。与集合的操作符相似,但集合的操作符只能用于集合的一系列数据变换。而作用域函数可以应用与所有对象,他可以对所有对象做一系列的操作

    //常用的作用域函数有如下
    run{...}
    with(T){...}
    let{...}
    apply{...}
    also{...}
    
    
    object  Test {
        @JvmStatic
        fun main(){
            val user=User("xiaoming")
            //let 与run 都会返回闭包的执行结果,区别自安于let 有闭包参数,而run 没有闭包参数
            var letResult:String =user.let { user: User -> "let::${user.javaClass}" }
            println(letResult)
            //this 指代 user(调用者)本身
            val runResult:String = user.run { "run: ${this.javaClass}" }
            println(runResult)
    
    		//also与apply 都不返回闭包的执行结果,区别在于also 有闭包参数,而apply没有闭包参数
            user.also {
                println("also :: ${it.javaClass}")
            }
            user.apply {
                println("applu :: ${this.javaClass}")
            }
    
    		//takeIf 的闭包返回一个判断结果,为false时 takeIf会返回空
            user.takeIf {
               it.name.length>0
            }?.also {
                println("takeIf name:: ${user.name}")
            }?: println("takeIf 姓名为空")
    
            //takeUnless 与takeIf刚好相反,闭包的判断结果为true时函数会返回空
            user.takeUnless {
                it.name.length>0
            }?.also {
                println("takeUnless 姓名为空")
            }?: println("takeUnless 姓名为: ${user.name}")
       		
       		//with 比较特殊,不是以扩展函数的形式存在的,而是一个顶级函数
       		with(user){
    			this.name="with"
    		}
        }
    
    }
    data class User(var name:String)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    kotlin 集合常用的操作符

    元素操作类
    contain – 判断是否有指定元素
    elementAt – 返回对应的元素,越界会抛出IndexOutOfBoundsExceotion
    firstOrNull – 返回符合条件的第一个元素,没有返回null
    lastOrNull – 返回符合条件的第一个元素,没有返回null
    indexOf – 返回指定元素的下表,没有返回-1
    singleOrNull – 返回符合条件的单个元素,如果没有符合或超过一个,返回null

    判断类
    any – 判断集合中是否有满足条件的元素
    all – 判断集合中的元素是否都满足条件
    none – 判断集合中是否都不满足条件,是则返回true
    count – 查询集合中满足条件的元素个数
    reduce – 从第一项到最后一项进行累计

    过滤类
    filter – 过滤掉所有满足条件的元素
    filterNot – 过滤所有不满足条件的元素
    filterNotNull – 过滤所有不满足条件的元素
    take – 返回前n个元素

    转换类
    map – 转换成另一个集合(与上面我们实现的convert 方法作用一样)
    mapIndexed – 除了转换成另一个集合,还可以拿到Index (下标)
    mapNotNull – 执行转换前过滤掉为NUll 的元素
    flatMap – 自定义逻辑合并梨啊个集合
    groupBy – 按照某个条件分组,返回Map

    排序类
    reversed – 反序
    sorted – 升序
    sortedBy – 自定义排序
    sortedDescending – 降序

    运算符重载 & 中缀表达式

    在kotlin 中非常多的运算符都是通过重载来完成的

    //其中 1..100中的 .. 便是通过运算符的重载来变成一个区间值的。  
    //step 既不是关键字也不是函数,类似的就是中缀表达式
    fun main(args:Array<String>){
    	for(i in 1..100 step 20){
    		println("$i ")
    	}
    }
    
    
    //编译后,..会被编译成一个迭代器
    override fun iterator():IntIterator =IntProgressionIterator(first,last,setp)
    
    internal class IntProgressionIterator(first:Int,last:Int,val step:Int):IntIterator{
    	private var next = first
    	private val finalElement = last
    	private var hasNext:Boolen =if(setp>0) first <=last else first >= last
    
    	override fun hasNext():Boolen = hasNext
    
    	override fun nextInt() : Int{
    		val value = next
    		if(value == finalElement){
    			hasNext = false
    		}else{
    			next += step
    		}
    		return value
    	}
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    运算符重载 和 中缀表达式本质上都是一个特殊的函数,都是通过函数的调用完成的

    运算符的重载是有一个特点的。它一定是提前在kotlin 中定义的,不能凭空重载一个运算符。运算符是有上限的。当运算符不够的时候,我们需要通过中缀表达式扩展

    中缀表达式

    //中缀表达式定义 需要通过infix 来修饰方法。Int 是 vs 函数的函数接收者
    infix fun Int.vs(num:Int):CompareResult =
    	if(this - num < 0){
    		CompareResult.MORE
    	}else if(this - num > 0){
    		CompareResult.LESS
    	}else {
    		CompareResult.EQUAL
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    一个函数只有用于两个角色类型的对象时才将其声明为中缀函数
    推荐示例:and 、to 、zip 、vs
    反例:add
    如果一个方法会改动其接收者,那么不要声明为中缀形式

    kotlin 中的特殊符号

    反引号

    反引号作用:
    1.可以用来解决关键字冲突问题
    2.将一个不合法的字符串变成合法的 (例如下)

    //我们在命名一个函数的时候是不能用纯数字去命名的,必须以下划线或字母开头,然后才能使用数字
    使用`` 便可合法化
    
    fun `1234`(){}
    
    fun `` (){}
    
    fun `  `(){}
    
    fun main(args:Array<String>){
    	`1234`()
    	` `()
    	`  `()
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    该特性一般不会使用。除非这个类不希望被java 访问到时,

    kotlin 中如何比较对象
    //kotlin 中比较对象和值             java 比较对象和值
    a == b  比较值           <==>       a.equals(b)
    a === b 比较对象         <==>       a == b
    
    • 1
    • 2
    • 3
    类型链接
    public typealias A = File
    
    fun main(args:Array<String>){
    	val a:File=A("")
    }
    
    //例如kotlin 中 HasMap 就是通过typealias 来引用的java HashMap
    public typealias HasMap<K,V> = java.util.HasMap<K,V>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    DSL (Domain Specific Language-- 领域专用语言)

    DSL 分为外部DSL 、和内部DSL

    外部DSL(不依赖与其他的编程语言或自然语言)

    • JSON
    • XML
    • CSS
    • Makefile

    内部DSL(本省还会依赖于其他编程语言)

    • Anko kotlin 官方提供,通过DSL风格将安卓布局通过代码实现
    • Kolley
    • build.gradle

    DSL优点
    提高开发效率
    减少沟通成本

    DSL缺点
    很难设计一个通用的DSL

  • 相关阅读:
    【软件测试】设计优秀的测试用例
    VUE(0) : vue-element-admin[0] : 常用语法
    Haproxy搭建Web群集
    二叉树(上)
    Guacamole Web端配置使用
    大数据Flink(七十二):SQL窗口的概述和Over Windows
    金融风控信用评分卡建模(Kaggle give me credit数据集)
    [前端网站源码]基于HTML5,DIV CSS实现的宠物狗个性化服务网站前端(静态网页设计)
    即时通讯开发Netty实现心跳机制、断线重连机制
    Yolov安全帽佩戴检测 危险区域进入检测 - 深度学习 opencv 计算机竞赛
  • 原文地址:https://blog.csdn.net/qq_26057629/article/details/125443713