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")
}

循环与集合操作符

循环

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")
}
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")
	}
}

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)
	}
}

作用域函数

是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)
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
	}
}


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

运算符的重载是有一个特点的。它一定是提前在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
	}

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

kotlin 中的特殊符号

反引号

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

//我们在命名一个函数的时候是不能用纯数字去命名的,必须以下划线或字母开头,然后才能使用数字
使用`` 便可合法化

fun `1234`(){}

fun `` (){}

fun `  `(){}

fun main(args:Array<String>){
	`1234`()
	` `()
	`  `()
}

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

kotlin 中如何比较对象
//kotlin 中比较对象和值             java 比较对象和值
a == b  比较值           <==>       a.equals(b)
a === b 比较对象         <==>       a == b
类型链接
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>

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

DSL 分为外部DSL 、和内部DSL

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

  • JSON
  • XML
  • CSS
  • Makefile

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

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值