Kotlin 基础语法-04-高级特性
本文主要写kotlin中的解构、循环和集合操作符、 运算符重载、 作用域函数、 中缀表达式、DSL相关知识来展开。
- 解构
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
- 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")
})
- 集合操作符
类似于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
- 作用域函数
如果用习惯了集合操作符、突然你会想有没有一种东西或者工具能够操作对象、或者其他数据类型数据呢? 答案是、作用域函数。
在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
如果有一定的语言基础这些操作符只看名字就知道什么意思了吧、 注释很清楚了、如果还有不清楚的、我们讨论共同学习、
- 总结
时间原因, 运算符重载和中缀表达式 DSL 放在下篇文章,
多上手敲、多尝试、多思考、 有问题评论区我们共同讨论进步。